1use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
6use std::collections::{BTreeSet, HashSet, VecDeque};
7
8use super::types::{
9 AndersenPTA, ConstPropState, EraserState, FixpointSolver, IFCTracker, Interval, NullTracker,
10 Nullability, PDGraph, SecurityLevel, Sign, TaintState, TypestateAutomaton,
11};
12
13pub fn app(f: Expr, a: Expr) -> Expr {
14 Expr::App(Box::new(f), Box::new(a))
15}
16pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
17 app(app(f, a), b)
18}
19pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
20 app(app2(f, a, b), c)
21}
22pub fn cst(s: &str) -> Expr {
23 Expr::Const(Name::str(s), vec![])
24}
25pub fn prop() -> Expr {
26 Expr::Sort(Level::zero())
27}
28pub fn type0() -> Expr {
29 Expr::Sort(Level::succ(Level::zero()))
30}
31pub fn pi(bi: BinderInfo, name: &str, dom: Expr, body: Expr) -> Expr {
32 Expr::Pi(bi, Name::str(name), Box::new(dom), Box::new(body))
33}
34pub fn arrow(a: Expr, b: Expr) -> Expr {
35 pi(BinderInfo::Default, "_", a, b)
36}
37pub fn bvar(n: u32) -> Expr {
38 Expr::BVar(n)
39}
40pub fn nat_ty() -> Expr {
41 cst("Nat")
42}
43pub fn bool_ty() -> Expr {
44 cst("Bool")
45}
46pub fn string_ty() -> Expr {
47 cst("String")
48}
49pub fn list_ty(elem: Expr) -> Expr {
50 app(cst("List"), elem)
51}
52pub fn option_ty(elem: Expr) -> Expr {
53 app(cst("Option"), elem)
54}
55pub fn set_ty(elem: Expr) -> Expr {
56 app(cst("Set"), elem)
57}
58pub fn pair_ty(a: Expr, b: Expr) -> Expr {
59 app2(cst("Prod"), a, b)
60}
61pub fn lattice_ty() -> Expr {
63 arrow(type0(), type0())
64}
65pub fn lattice_bottom_ty() -> Expr {
67 pi(
68 BinderInfo::Default,
69 "L",
70 type0(),
71 arrow(app(cst("Lattice"), bvar(0)), bvar(1)),
72 )
73}
74pub fn lattice_top_ty() -> Expr {
76 pi(
77 BinderInfo::Default,
78 "L",
79 type0(),
80 arrow(app(cst("Lattice"), bvar(0)), bvar(1)),
81 )
82}
83pub fn lattice_join_ty() -> Expr {
85 pi(
86 BinderInfo::Default,
87 "L",
88 type0(),
89 arrow(
90 app(cst("Lattice"), bvar(0)),
91 arrow(bvar(1), arrow(bvar(2), bvar(3))),
92 ),
93 )
94}
95pub fn lattice_meet_ty() -> Expr {
97 pi(
98 BinderInfo::Default,
99 "L",
100 type0(),
101 arrow(
102 app(cst("Lattice"), bvar(0)),
103 arrow(bvar(1), arrow(bvar(2), bvar(3))),
104 ),
105 )
106}
107pub fn lattice_leq_ty() -> Expr {
109 pi(
110 BinderInfo::Default,
111 "L",
112 type0(),
113 arrow(
114 app(cst("Lattice"), bvar(0)),
115 arrow(bvar(1), arrow(bvar(2), prop())),
116 ),
117 )
118}
119pub fn moore_family_ty() -> Expr {
121 pi(
122 BinderInfo::Default,
123 "A",
124 type0(),
125 arrow(set_ty(set_ty(bvar(0))), prop()),
126 )
127}
128pub fn complete_lattice_galois_ty() -> Expr {
130 pi(
131 BinderInfo::Default,
132 "L",
133 type0(),
134 arrow(
135 app(cst("GaloisConn"), bvar(0)),
136 app(cst("CompleteLattice"), bvar(1)),
137 ),
138 )
139}
140pub fn concrete_semantics_ty() -> Expr {
142 arrow(cst("Program"), set_ty(cst("ConcreteState")))
143}
144pub fn abstract_semantics_ty() -> Expr {
146 arrow(cst("Program"), cst("AbsDom"))
147}
148pub fn galois_connection_ty() -> Expr {
151 pair_ty(
152 arrow(cst("ConcreteState"), cst("AbsDom")),
153 arrow(cst("AbsDom"), cst("ConcreteState")),
154 )
155}
156pub fn abstraction_ty() -> Expr {
158 arrow(concrete_semantics_ty(), cst("AbsDom"))
159}
160pub fn concretization_ty() -> Expr {
162 arrow(cst("AbsDom"), concrete_semantics_ty())
163}
164pub fn galois_insertion_ty() -> Expr {
166 arrow(galois_connection_ty(), prop())
167}
168pub fn widening_ty() -> Expr {
170 arrow(cst("AbsDom"), arrow(cst("AbsDom"), cst("AbsDom")))
171}
172pub fn narrowing_ty() -> Expr {
174 arrow(cst("AbsDom"), arrow(cst("AbsDom"), cst("AbsDom")))
175}
176pub fn widening_terminates_ty() -> Expr {
178 pi(
179 BinderInfo::Default,
180 "f",
181 arrow(cst("AbsDom"), cst("AbsDom")),
182 app(
183 cst("Terminates"),
184 app2(cst("fixpoint_widen"), bvar(0), cst("Widening")),
185 ),
186 )
187}
188pub fn abstract_interp_sound_ty() -> Expr {
190 pi(
191 BinderInfo::Default,
192 "prog",
193 cst("Program"),
194 app(
195 app(cst("Leq"), app(cst("α"), app(cst("collect"), bvar(0)))),
196 app(cst("abs_semantics"), bvar(0)),
197 ),
198 )
199}
200pub fn narrowing_refines_post_ty() -> Expr {
202 pi(
203 BinderInfo::Default,
204 "x",
205 cst("AbsDom"),
206 pi(
207 BinderInfo::Default,
208 "y",
209 cst("AbsDom"),
210 arrow(
211 app2(cst("Leq"), bvar(0), bvar(1)),
212 app(
213 app(
214 cst("Leq"),
215 app2(cst("Narrowing"), bvar(1), app(cst("f"), bvar(2))),
216 ),
217 bvar(2),
218 ),
219 ),
220 ),
221 )
222}
223pub fn heap_graph_ty() -> Expr {
225 type0()
226}
227pub fn heap_node_ty() -> Expr {
229 type0()
230}
231pub fn sharing_pred_ty() -> Expr {
234 arrow(
235 heap_graph_ty(),
236 arrow(heap_node_ty(), arrow(heap_node_ty(), prop())),
237 )
238}
239pub fn cyclic_pred_ty() -> Expr {
242 arrow(heap_graph_ty(), arrow(heap_node_ty(), prop()))
243}
244pub fn shape_descriptor_ty() -> Expr {
246 type0()
247}
248pub fn shape_join_ty() -> Expr {
250 arrow(
251 shape_descriptor_ty(),
252 arrow(shape_descriptor_ty(), shape_descriptor_ty()),
253 )
254}
255pub fn shape_transfer_ty() -> Expr {
257 arrow(
258 cst("HeapOp"),
259 arrow(shape_descriptor_ty(), shape_descriptor_ty()),
260 )
261}
262pub fn shape_sound_ty() -> Expr {
264 pi(
265 BinderInfo::Default,
266 "op",
267 cst("HeapOp"),
268 pi(
269 BinderInfo::Default,
270 "s",
271 shape_descriptor_ty(),
272 app(
273 cst("OverApprox"),
274 app2(cst("shape_transfer"), bvar(1), bvar(0)),
275 ),
276 ),
277 )
278}
279pub fn three_valued_ty() -> Expr {
281 type0()
282}
283pub fn must_alias_ty() -> Expr {
285 arrow(
286 heap_graph_ty(),
287 arrow(heap_node_ty(), arrow(heap_node_ty(), three_valued_ty())),
288 )
289}
290pub fn alloc_site_ty() -> Expr {
292 nat_ty()
293}
294pub fn points_to_ty() -> Expr {
296 arrow(cst("Var"), set_ty(alloc_site_ty()))
297}
298pub fn andersen_analysis_ty() -> Expr {
300 arrow(cst("Program"), points_to_ty())
301}
302pub fn steensgaard_analysis_ty() -> Expr {
305 arrow(cst("Program"), arrow(cst("Var"), cst("Var")))
306}
307pub fn andersen_sound_ty() -> Expr {
309 pi(
310 BinderInfo::Default,
311 "prog",
312 cst("Program"),
313 app(cst("Sound"), app(cst("AndersenAnalysis"), bvar(0))),
314 )
315}
316pub fn steensgaard_sub_andersen_ty() -> Expr {
318 pi(
319 BinderInfo::Default,
320 "prog",
321 cst("Program"),
322 app(
323 app(cst("Leq"), app(cst("SteensgaardAnalysis"), bvar(0))),
324 app(cst("AndersenAnalysis"), bvar(0)),
325 ),
326 )
327}
328pub fn andersen_cubic_ty() -> Expr {
330 app(
331 cst("TimeComplexity"),
332 app(cst("CubicN"), cst("AndersenAnalysis")),
333 )
334}
335pub fn steensgaard_almost_linear_ty() -> Expr {
337 app(
338 cst("TimeComplexity"),
339 app(cst("InvAckermann"), cst("SteensgaardAnalysis")),
340 )
341}
342pub fn alias_result_ty() -> Expr {
344 arrow(cst("Var"), arrow(cst("Var"), prop()))
345}
346pub fn may_alias_ty() -> Expr {
348 arrow(
349 cst("Program"),
350 arrow(cst("Var"), arrow(cst("Var"), bool_ty())),
351 )
352}
353pub fn must_alias_pair_ty() -> Expr {
355 arrow(
356 cst("Program"),
357 arrow(cst("Var"), arrow(cst("Var"), bool_ty())),
358 )
359}
360pub fn type_based_alias_ty() -> Expr {
362 arrow(cst("IRType"), arrow(cst("IRType"), bool_ty()))
363}
364pub fn no_alias_ty() -> Expr {
366 arrow(cst("Var"), arrow(cst("Var"), prop()))
367}
368pub fn alias_undecidable_ty() -> Expr {
370 app(cst("Undecidable"), cst("ExactAliasAnalysis"))
371}
372pub fn soft_type_ty() -> Expr {
374 type0()
375}
376pub fn soft_type_check_ty() -> Expr {
378 arrow(cst("Program"), arrow(soft_type_ty(), bool_ty()))
379}
380pub fn refinement_type_ty() -> Expr {
382 arrow(type0(), arrow(arrow(bvar(0), prop()), type0()))
383}
384pub fn effect_type_ty() -> Expr {
386 arrow(type0(), arrow(cst("EffectSet"), type0()))
387}
388pub fn effect_subtype_ty() -> Expr {
390 arrow(effect_type_ty(), arrow(effect_type_ty(), prop()))
391}
392pub fn liquid_haskell_sound_ty() -> Expr {
394 pi(
395 BinderInfo::Default,
396 "prog",
397 cst("Program"),
398 arrow(
399 app(cst("liquid_type_check"), bvar(0)),
400 app(cst("no_runtime_errors"), bvar(1)),
401 ),
402 )
403}
404pub fn call_site_ty() -> Expr {
406 nat_ty()
407}
408pub fn abstract_closure_ty() -> Expr {
410 type0()
411}
412pub fn zero_cfa_ty() -> Expr {
415 arrow(
416 cst("Program"),
417 arrow(call_site_ty(), set_ty(abstract_closure_ty())),
418 )
419}
420pub fn k_cfa_ty() -> Expr {
423 arrow(
424 nat_ty(),
425 arrow(
426 cst("Program"),
427 arrow(
428 pair_ty(call_site_ty(), list_ty(call_site_ty())),
429 set_ty(abstract_closure_ty()),
430 ),
431 ),
432 )
433}
434pub fn cfa_overapprox_ty() -> Expr {
436 pi(
437 BinderInfo::Default,
438 "k",
439 nat_ty(),
440 pi(
441 BinderInfo::Default,
442 "prog",
443 cst("Program"),
444 app(cst("Overapproximates"), app2(cst("KCFA"), bvar(1), bvar(0))),
445 ),
446 )
447}
448pub fn cfa_monotone_k_ty() -> Expr {
450 pi(
451 BinderInfo::Default,
452 "k",
453 nat_ty(),
454 app(
455 app(cst("Leq"), app2(cst("KCFA"), bvar(0), cst("prog"))),
456 app2(cst("KCFA"), app(cst("Succ"), bvar(0)), cst("prog")),
457 ),
458 )
459}
460pub fn k_cfa_complexity_ty() -> Expr {
462 pi(
463 BinderInfo::Default,
464 "k",
465 nat_ty(),
466 arrow(
467 app(cst("Ge"), app2(cst("Ge"), bvar(0), nat_ty())),
468 app(cst("EXPTIMEComplete"), app(cst("KCFA"), bvar(1))),
469 ),
470 )
471}
472pub fn effect_ty() -> Expr {
474 type0()
475}
476pub fn effect_set_ty() -> Expr {
478 set_ty(effect_ty())
479}
480pub fn read_effect_ty() -> Expr {
482 arrow(cst("Var"), effect_ty())
483}
484pub fn write_effect_ty() -> Expr {
486 arrow(cst("Var"), effect_ty())
487}
488pub fn exn_effect_ty() -> Expr {
490 arrow(cst("ExnType"), effect_ty())
491}
492pub fn infer_effects_ty() -> Expr {
494 arrow(cst("Program"), cst("EffectMap"))
495}
496pub fn effect_sound_ty() -> Expr {
498 pi(
499 BinderInfo::Default,
500 "prog",
501 cst("Program"),
502 app(
503 app(cst("Superset"), app(cst("infer_effects"), bvar(0))),
504 app(cst("actual_effects"), bvar(0)),
505 ),
506 )
507}
508pub fn pure_function_ty() -> Expr {
510 arrow(cst("Expr"), prop())
511}
512pub fn resource_type_ty() -> Expr {
514 type0()
515}
516pub fn usage_annotation_ty() -> Expr {
518 type0()
519}
520pub fn linear_type_ty() -> Expr {
522 arrow(resource_type_ty(), prop())
523}
524pub fn affine_type_ty() -> Expr {
526 arrow(resource_type_ty(), prop())
527}
528pub fn resource_usage_analysis_ty() -> Expr {
531 arrow(cst("Program"), arrow(cst("Var"), usage_annotation_ty()))
532}
533pub fn leak_freedom_ty() -> Expr {
535 arrow(cst("Program"), prop())
536}
537pub fn linear_type_leak_free_ty() -> Expr {
539 pi(
540 BinderInfo::Default,
541 "prog",
542 cst("Program"),
543 arrow(
544 app(cst("WellTypedLinear"), bvar(0)),
545 app(cst("LeakFreedom"), bvar(1)),
546 ),
547 )
548}
549pub fn usage_count_sound_ty() -> Expr {
551 pi(
552 BinderInfo::Default,
553 "prog",
554 cst("Program"),
555 app(cst("Sound"), app(cst("ResourceUsageAnalysis"), bvar(0))),
556 )
557}
558pub fn thread_ty() -> Expr {
560 nat_ty()
561}
562pub fn lock_set_ty() -> Expr {
564 set_ty(nat_ty())
565}
566pub fn happens_before_ty() -> Expr {
568 arrow(cst("Event"), arrow(cst("Event"), prop()))
569}
570pub fn data_race_ty() -> Expr {
574 arrow(cst("Event"), arrow(cst("Event"), prop()))
575}
576pub fn eraser_lock_set_ty() -> Expr {
579 arrow(thread_ty(), arrow(cst("MemLoc"), lock_set_ty()))
580}
581pub fn eraser_invariant_ty() -> Expr {
583 pi(
584 BinderInfo::Default,
585 "v",
586 cst("MemLoc"),
587 arrow(
588 app(cst("NonEmpty"), app(cst("C"), bvar(0))),
589 app(cst("NoRace"), bvar(1)),
590 ),
591 )
592}
593pub fn tsan_sound_ty() -> Expr {
595 pi(
596 BinderInfo::Default,
597 "prog",
598 cst("Program"),
599 arrow(
600 app(cst("HasRace"), bvar(0)),
601 app(cst("TSanReports"), bvar(1)),
602 ),
603 )
604}
605pub fn data_race_freedom_ty() -> Expr {
607 arrow(cst("Program"), prop())
608}
609pub fn drf_sequential_ty() -> Expr {
611 pi(
612 BinderInfo::Default,
613 "prog",
614 cst("Program"),
615 arrow(
616 app(cst("DataRaceFreedom"), bvar(0)),
617 app(cst("SeqConsistent"), bvar(1)),
618 ),
619 )
620}
621pub fn taint_source_ty() -> Expr {
623 type0()
624}
625pub fn taint_sink_ty() -> Expr {
627 type0()
628}
629pub fn sanitizer_ty() -> Expr {
631 type0()
632}
633pub fn taint_label_ty() -> Expr {
635 arrow(cst("Var"), bool_ty())
636}
637pub fn taint_propagation_ty() -> Expr {
640 arrow(cst("Program"), arrow(taint_label_ty(), taint_label_ty()))
641}
642pub fn taint_violation_ty() -> Expr {
645 arrow(
646 cst("Program"),
647 arrow(
648 taint_label_ty(),
649 arrow(set_ty(pair_ty(cst("Var"), taint_sink_ty())), prop()),
650 ),
651 )
652}
653pub fn taint_sound_ty() -> Expr {
655 pi(
656 BinderInfo::Default,
657 "prog",
658 cst("Program"),
659 app(cst("Sound"), app(cst("TaintPropagation"), bvar(0))),
660 )
661}
662pub fn taint_no_false_neg_ty() -> Expr {
664 pi(
665 BinderInfo::Default,
666 "prog",
667 cst("Program"),
668 arrow(
669 app(cst("RealViolation"), bvar(0)),
670 app(cst("Reported"), bvar(1)),
671 ),
672 )
673}
674pub fn sep_logic_heap_ty() -> Expr {
676 arrow(cst("Addr"), option_ty(cst("Val")))
677}
678pub fn sep_conj_ty() -> Expr {
680 arrow(
681 arrow(sep_logic_heap_ty(), prop()),
682 arrow(
683 arrow(sep_logic_heap_ty(), prop()),
684 arrow(sep_logic_heap_ty(), prop()),
685 ),
686 )
687}
688pub fn sep_imp_ty() -> Expr {
690 arrow(
691 arrow(sep_logic_heap_ty(), prop()),
692 arrow(
693 arrow(sep_logic_heap_ty(), prop()),
694 arrow(sep_logic_heap_ty(), prop()),
695 ),
696 )
697}
698pub fn points_to_cell_ty() -> Expr {
700 arrow(
701 cst("Addr"),
702 arrow(cst("Val"), arrow(sep_logic_heap_ty(), prop())),
703 )
704}
705pub fn frame_rule_ty() -> Expr {
707 pi(
708 BinderInfo::Default,
709 "P",
710 arrow(sep_logic_heap_ty(), prop()),
711 pi(
712 BinderInfo::Default,
713 "Q",
714 arrow(sep_logic_heap_ty(), prop()),
715 pi(
716 BinderInfo::Default,
717 "R",
718 arrow(sep_logic_heap_ty(), prop()),
719 arrow(
720 app3(cst("HoareTriple"), bvar(2), cst("prog"), bvar(1)),
721 app3(
722 cst("HoareTriple"),
723 app2(cst("SepConj"), bvar(2), bvar(0)),
724 cst("prog"),
725 app2(cst("SepConj"), bvar(1), bvar(0)),
726 ),
727 ),
728 ),
729 ),
730 )
731}
732pub fn heap_shape_tree_pred_ty() -> Expr {
734 arrow(heap_node_ty(), arrow(sep_logic_heap_ty(), prop()))
735}
736pub fn memory_safety_ty() -> Expr {
738 arrow(
739 cst("Program"),
740 arrow(arrow(sep_logic_heap_ty(), prop()), prop()),
741 )
742}
743pub fn ownership_transfer_ty() -> Expr {
746 arrow(
747 arrow(sep_logic_heap_ty(), prop()),
748 arrow(arrow(sep_logic_heap_ty(), prop()), prop()),
749 )
750}
751pub fn typestate_ty() -> Expr {
753 type0()
754}
755pub fn typestate_protocol_ty() -> Expr {
757 arrow(typestate_ty(), set_ty(typestate_ty()))
758}
759pub fn typestate_transition_ty() -> Expr {
762 arrow(
763 typestate_ty(),
764 arrow(cst("Op"), arrow(typestate_ty(), prop())),
765 )
766}
767pub fn typestate_check_ty() -> Expr {
770 arrow(cst("Program"), arrow(typestate_protocol_ty(), prop()))
771}
772pub fn must_use_resource_ty() -> Expr {
774 arrow(typestate_ty(), prop())
775}
776pub fn typestate_sound_ty() -> Expr {
778 pi(
779 BinderInfo::Default,
780 "prog",
781 cst("Program"),
782 arrow(
783 app(cst("TypestateCheck"), bvar(0)),
784 app(cst("NoProtocolViolation"), bvar(1)),
785 ),
786 )
787}
788pub fn region_ty() -> Expr {
790 nat_ty()
791}
792pub fn region_annotation_ty() -> Expr {
794 arrow(cst("Expr"), region_ty())
795}
796pub fn escape_analysis_ty() -> Expr {
799 arrow(cst("Program"), arrow(cst("Var"), bool_ty()))
800}
801pub fn region_inference_ty() -> Expr {
804 arrow(cst("Program"), region_annotation_ty())
805}
806pub fn escape_sound_ty() -> Expr {
808 pi(
809 BinderInfo::Default,
810 "prog",
811 cst("Program"),
812 pi(
813 BinderInfo::Default,
814 "v",
815 cst("Var"),
816 arrow(
817 app(
818 app(cst("Not"), app2(cst("EscapeAnalysis"), bvar(1), bvar(0))),
819 nat_ty(),
820 ),
821 app2(cst("StackAllocated"), bvar(1), bvar(0)),
822 ),
823 ),
824 )
825}
826pub fn region_subtyping_ty() -> Expr {
828 arrow(region_ty(), arrow(region_ty(), prop()))
829}
830pub fn monadic_effect_ty() -> Expr {
833 arrow(type0(), arrow(effect_set_ty(), type0()))
834}
835pub fn graded_monad_ty() -> Expr {
838 arrow(arrow(effect_set_ty(), arrow(type0(), type0())), prop())
839}
840pub fn capability_set_ty() -> Expr {
842 set_ty(cst("Capability"))
843}
844pub fn capability_judgment_ty() -> Expr {
847 arrow(
848 cst("Context"),
849 arrow(cst("Expr"), arrow(effect_type_ty(), prop())),
850 )
851}
852pub fn effect_polymorphism_ty() -> Expr {
854 pi(
855 BinderInfo::Default,
856 "f",
857 effect_set_ty(),
858 pi(
859 BinderInfo::Default,
860 "g",
861 effect_set_ty(),
862 pi(
863 BinderInfo::Default,
864 "T",
865 type0(),
866 arrow(
867 app2(cst("HasEffectType"), bvar(0), bvar(2)),
868 app2(
869 cst("HasEffectType"),
870 bvar(0),
871 app2(cst("EffectUnion"), bvar(2), bvar(1)),
872 ),
873 ),
874 ),
875 ),
876 )
877}
878pub fn algebraic_effect_handler_ty() -> Expr {
881 arrow(effect_set_ty(), arrow(type0(), type0()))
882}
883pub fn gradual_type_ty() -> Expr {
885 type0()
886}
887pub fn unknown_type_ty() -> Expr {
889 gradual_type_ty()
890}
891pub fn consistency_rel_ty() -> Expr {
893 arrow(gradual_type_ty(), arrow(gradual_type_ty(), prop()))
894}
895pub fn cast_insertion_ty() -> Expr {
897 arrow(cst("GradualExpr"), cst("StaticExpr"))
898}
899pub fn cast_correctness_ty() -> Expr {
902 pi(
903 BinderInfo::Default,
904 "e",
905 cst("GradualExpr"),
906 app(
907 app(
908 cst("Eq"),
909 app(cst("eval"), app(cst("CastInsertion"), bvar(0))),
910 ),
911 app(cst("gradual_eval"), bvar(0)),
912 ),
913 )
914}
915pub fn blame_theorem_ty() -> Expr {
917 pi(
918 BinderInfo::Default,
919 "e",
920 cst("GradualExpr"),
921 arrow(
922 app(cst("CastFails"), bvar(0)),
923 app(cst("BlameCorrect"), bvar(1)),
924 ),
925 )
926}
927pub fn liquid_type_ty() -> Expr {
930 arrow(
931 cst("BaseType"),
932 arrow(cst("Qualifier"), cst("RefinementType")),
933 )
934}
935pub fn qualifier_instantiation_ty() -> Expr {
938 arrow(
939 cst("Template"),
940 arrow(cst("Substitution"), cst("Qualifier")),
941 )
942}
943pub fn subtyping_refinement_ty() -> Expr {
946 arrow(cst("RefinementType"), arrow(cst("RefinementType"), prop()))
947}
948pub fn refinement_inference_ty() -> Expr {
951 arrow(cst("Program"), arrow(cst("Var"), cst("RefinementType")))
952}
953pub fn liquid_type_complete_ty() -> Expr {
955 pi(
956 BinderInfo::Default,
957 "prog",
958 cst("Program"),
959 arrow(
960 app(cst("QualifierSetFinite"), bvar(0)),
961 app(cst("RefinementInferenceComplete"), bvar(1)),
962 ),
963 )
964}
965pub fn security_label_ty() -> Expr {
967 type0()
968}
969pub fn secrecy_lattice_ty() -> Expr {
971 arrow(security_label_ty(), arrow(security_label_ty(), prop()))
972}
973pub fn label_env_ty() -> Expr {
975 arrow(cst("Var"), security_label_ty())
976}
977pub fn non_interference_ty() -> Expr {
980 arrow(cst("Program"), arrow(label_env_ty(), prop()))
981}
982pub fn declassification_ty() -> Expr {
985 arrow(
986 cst("Expr"),
987 arrow(security_label_ty(), arrow(security_label_ty(), prop())),
988 )
989}
990pub fn ifc_type_system_ty() -> Expr {
993 arrow(
994 cst("Context"),
995 arrow(cst("Expr"), arrow(cst("LabeledType"), prop())),
996 )
997}
998pub fn ni_theorem_ty() -> Expr {
1000 pi(
1001 BinderInfo::Default,
1002 "prog",
1003 cst("Program"),
1004 pi(
1005 BinderInfo::Default,
1006 "env",
1007 label_env_ty(),
1008 arrow(
1009 app2(cst("IFC_typed"), bvar(1), bvar(0)),
1010 app2(cst("NonInterference"), bvar(2), bvar(1)),
1011 ),
1012 ),
1013 )
1014}
1015pub fn constant_folding_ty() -> Expr {
1017 arrow(cst("Expr"), cst("Expr"))
1018}
1019pub fn constant_propagation_ty() -> Expr {
1022 arrow(cst("Program"), arrow(cst("Var"), option_ty(cst("Val"))))
1023}
1024pub fn const_fold_correct_ty() -> Expr {
1026 pi(
1027 BinderInfo::Default,
1028 "e",
1029 cst("Expr"),
1030 app(
1031 app(
1032 cst("Eq"),
1033 app(cst("eval"), app(cst("ConstantFolding"), bvar(0))),
1034 ),
1035 app(cst("eval"), bvar(0)),
1036 ),
1037 )
1038}
1039pub fn interval_domain_ty() -> Expr {
1041 type0()
1042}
1043pub fn bitfield_domain_ty() -> Expr {
1045 type0()
1046}
1047pub fn value_range_analysis_ty() -> Expr {
1050 arrow(cst("Program"), arrow(cst("Var"), interval_domain_ty()))
1051}
1052pub fn vra_sound_ty() -> Expr {
1054 pi(
1055 BinderInfo::Default,
1056 "prog",
1057 cst("Program"),
1058 app(cst("Sound"), app(cst("ValueRangeAnalysis"), bvar(0))),
1059 )
1060}
1061pub fn nullability_annotation_ty() -> Expr {
1064 arrow(type0(), arrow(bool_ty(), type0()))
1065}
1066pub fn null_pointer_analysis_ty() -> Expr {
1069 arrow(cst("Program"), arrow(cst("Var"), three_valued_ty()))
1070}
1071pub fn definite_assignment_ty() -> Expr {
1074 arrow(cst("Program"), arrow(cst("Var"), prop()))
1075}
1076pub fn null_safety_ty() -> Expr {
1078 arrow(cst("Program"), prop())
1079}
1080pub fn null_analysis_sound_ty() -> Expr {
1082 pi(
1083 BinderInfo::Default,
1084 "prog",
1085 cst("Program"),
1086 app(cst("Sound"), app(cst("NullPointerAnalysis"), bvar(0))),
1087 )
1088}
1089pub fn lock_order_ty() -> Expr {
1091 arrow(cst("Lock"), arrow(cst("Lock"), prop()))
1092}
1093pub fn deadlock_freedom_ty() -> Expr {
1095 arrow(cst("Program"), prop())
1096}
1097pub fn lock_order_acyclic_ty() -> Expr {
1099 pi(
1100 BinderInfo::Default,
1101 "prog",
1102 cst("Program"),
1103 arrow(
1104 app(cst("AcyclicLockOrder"), bvar(0)),
1105 app(cst("DeadlockFreedom"), bvar(1)),
1106 ),
1107 )
1108}
1109pub fn atomic_block_ty() -> Expr {
1112 arrow(cst("Program"), arrow(cst("Stmt"), prop()))
1113}
1114pub fn atomicity_serializability_ty() -> Expr {
1116 pi(
1117 BinderInfo::Default,
1118 "prog",
1119 cst("Program"),
1120 pi(
1121 BinderInfo::Default,
1122 "s",
1123 cst("Stmt"),
1124 arrow(
1125 app2(cst("AtomicBlock"), bvar(1), bvar(0)),
1126 app2(cst("SerializableExec"), bvar(2), bvar(1)),
1127 ),
1128 ),
1129 )
1130}
1131pub fn lock_set_analysis_ty() -> Expr {
1134 arrow(
1135 cst("Program"),
1136 arrow(thread_ty(), arrow(cst("MemLoc"), lock_set_ty())),
1137 )
1138}
1139pub fn ownership_type_ty() -> Expr {
1141 type0()
1142}
1143pub fn borrow_kind_ty() -> Expr {
1145 type0()
1146}
1147pub fn lifetime_ty() -> Expr {
1149 nat_ty()
1150}
1151pub fn borrow_check_ty() -> Expr {
1153 arrow(cst("Program"), prop())
1154}
1155pub fn ownership_unique_ty() -> Expr {
1157 arrow(ownership_type_ty(), prop())
1158}
1159pub fn borrow_check_mem_safe_ty() -> Expr {
1161 pi(
1162 BinderInfo::Default,
1163 "prog",
1164 cst("Program"),
1165 arrow(
1166 app(cst("BorrowCheck"), bvar(0)),
1167 app(cst("MemorySafe"), bvar(1)),
1168 ),
1169 )
1170}
1171pub fn lifetime_subtyping_ty() -> Expr {
1173 arrow(lifetime_ty(), arrow(lifetime_ty(), prop()))
1174}
1175pub fn non_lexical_lifetime_ty() -> Expr {
1178 arrow(cst("Program"), cst("LifetimeAnnotation"))
1179}
1180pub fn data_dependence_ty() -> Expr {
1182 arrow(cst("Stmt"), arrow(cst("Stmt"), prop()))
1183}
1184pub fn control_dependence_ty() -> Expr {
1186 arrow(cst("Stmt"), arrow(cst("Stmt"), prop()))
1187}
1188pub fn program_dependence_graph_ty() -> Expr {
1191 arrow(cst("Program"), cst("PDG"))
1192}
1193pub fn backward_slice_ty() -> Expr {
1196 arrow(
1197 cst("PDG"),
1198 arrow(cst("SliceCriterion"), set_ty(cst("Stmt"))),
1199 )
1200}
1201pub fn forward_slice_ty() -> Expr {
1204 arrow(
1205 cst("PDG"),
1206 arrow(cst("SliceCriterion"), set_ty(cst("Stmt"))),
1207 )
1208}
1209pub fn slice_correct_ty() -> Expr {
1211 pi(
1212 BinderInfo::Default,
1213 "prog",
1214 cst("Program"),
1215 pi(
1216 BinderInfo::Default,
1217 "c",
1218 cst("SliceCriterion"),
1219 app(
1220 cst("PreservesSemantics"),
1221 app2(
1222 cst("BackwardSlice"),
1223 app(cst("ProgramDependenceGraph"), bvar(1)),
1224 bvar(0),
1225 ),
1226 ),
1227 ),
1228 )
1229}
1230pub fn build_static_analysis_env() -> Environment {
1232 let mut env = Environment::new();
1233 let axioms: &[(&str, Expr)] = &[
1234 ("Lattice", lattice_ty()),
1235 ("LatticeBottom", lattice_bottom_ty()),
1236 ("LatticeTop", lattice_top_ty()),
1237 ("LatticeJoin", lattice_join_ty()),
1238 ("LatticeMeet", lattice_meet_ty()),
1239 ("LatticeLeq", lattice_leq_ty()),
1240 ("MooreFamily", moore_family_ty()),
1241 ("CompleteLattice_GaloisConn", complete_lattice_galois_ty()),
1242 ("ConcreteSemantics", concrete_semantics_ty()),
1243 ("AbstractSemantics", abstract_semantics_ty()),
1244 ("GaloisConnection", galois_connection_ty()),
1245 ("Abstraction", abstraction_ty()),
1246 ("Concretization", concretization_ty()),
1247 ("GaloisInsertion", galois_insertion_ty()),
1248 ("Widening", widening_ty()),
1249 ("Narrowing", narrowing_ty()),
1250 ("Widening_Terminates", widening_terminates_ty()),
1251 ("AbstractInterp_Sound", abstract_interp_sound_ty()),
1252 ("Narrowing_RefinesPost", narrowing_refines_post_ty()),
1253 ("HeapGraph", heap_graph_ty()),
1254 ("HeapNode", heap_node_ty()),
1255 ("SharingPred", sharing_pred_ty()),
1256 ("CyclicPred", cyclic_pred_ty()),
1257 ("ShapeDescriptor", shape_descriptor_ty()),
1258 ("shape_join", shape_join_ty()),
1259 ("shape_transfer", shape_transfer_ty()),
1260 ("ShapeSound", shape_sound_ty()),
1261 ("ThreeValued", three_valued_ty()),
1262 ("MustAlias", must_alias_ty()),
1263 ("AllocSite", alloc_site_ty()),
1264 ("PointsTo", points_to_ty()),
1265 ("AndersenAnalysis", andersen_analysis_ty()),
1266 ("SteensgaardAnalysis", steensgaard_analysis_ty()),
1267 ("Andersen_Sound", andersen_sound_ty()),
1268 ("Steensgaard_SubAndersen", steensgaard_sub_andersen_ty()),
1269 ("Andersen_Cubic", andersen_cubic_ty()),
1270 ("Steensgaard_AlmostLinear", steensgaard_almost_linear_ty()),
1271 ("AliasResult", alias_result_ty()),
1272 ("MayAlias", may_alias_ty()),
1273 ("MustAliasPair", must_alias_pair_ty()),
1274 ("TypeBasedAlias", type_based_alias_ty()),
1275 ("NoAlias", no_alias_ty()),
1276 ("Alias_Undecidable", alias_undecidable_ty()),
1277 ("SoftType", soft_type_ty()),
1278 ("SoftTypeCheck", soft_type_check_ty()),
1279 ("RefinementType", refinement_type_ty()),
1280 ("EffectType", effect_type_ty()),
1281 ("EffectSubtype", effect_subtype_ty()),
1282 ("Liquid_Haskell_Sound", liquid_haskell_sound_ty()),
1283 ("CallSite", call_site_ty()),
1284 ("AbstractClosure", abstract_closure_ty()),
1285 ("ZeroCFA", zero_cfa_ty()),
1286 ("KCFA", k_cfa_ty()),
1287 ("CFA_Overapprox", cfa_overapprox_ty()),
1288 ("CFA_Monotone_in_k", cfa_monotone_k_ty()),
1289 ("KCFA_Complexity", k_cfa_complexity_ty()),
1290 ("Effect", effect_ty()),
1291 ("EffectSet", effect_set_ty()),
1292 ("ReadEffect", read_effect_ty()),
1293 ("WriteEffect", write_effect_ty()),
1294 ("ExnEffect", exn_effect_ty()),
1295 ("infer_effects", infer_effects_ty()),
1296 ("EffectSound", effect_sound_ty()),
1297 ("PureFunction", pure_function_ty()),
1298 ("ResourceType", resource_type_ty()),
1299 ("UsageAnnotation", usage_annotation_ty()),
1300 ("LinearType", linear_type_ty()),
1301 ("AffineType", affine_type_ty()),
1302 ("ResourceUsageAnalysis", resource_usage_analysis_ty()),
1303 ("LeakFreedom", leak_freedom_ty()),
1304 ("LinearType_LeakFree", linear_type_leak_free_ty()),
1305 ("UsageCount_Sound", usage_count_sound_ty()),
1306 ("Thread", thread_ty()),
1307 ("LockSet", lock_set_ty()),
1308 ("HappensBefore", happens_before_ty()),
1309 ("DataRace", data_race_ty()),
1310 ("EraserLockSet", eraser_lock_set_ty()),
1311 ("Eraser_Invariant", eraser_invariant_ty()),
1312 ("TSan_Sound", tsan_sound_ty()),
1313 ("DataRaceFreedom", data_race_freedom_ty()),
1314 ("DRF_Sequential", drf_sequential_ty()),
1315 ("TaintSource", taint_source_ty()),
1316 ("TaintSink", taint_sink_ty()),
1317 ("Sanitizer", sanitizer_ty()),
1318 ("TaintLabel", taint_label_ty()),
1319 ("TaintPropagation", taint_propagation_ty()),
1320 ("TaintViolation", taint_violation_ty()),
1321 ("Taint_Sound", taint_sound_ty()),
1322 ("Taint_NoFalseNegatives", taint_no_false_neg_ty()),
1323 ("SepLogicHeap", sep_logic_heap_ty()),
1324 ("SepConj", sep_conj_ty()),
1325 ("SepImp", sep_imp_ty()),
1326 ("PointsToCell", points_to_cell_ty()),
1327 ("FrameRule", frame_rule_ty()),
1328 ("HeapShape_TreePred", heap_shape_tree_pred_ty()),
1329 ("MemorySafety", memory_safety_ty()),
1330 ("OwnershipTransfer", ownership_transfer_ty()),
1331 ("Typestate", typestate_ty()),
1332 ("TypestateProtocol", typestate_protocol_ty()),
1333 ("TypestateTransition", typestate_transition_ty()),
1334 ("TypestateCheck", typestate_check_ty()),
1335 ("MustUseResource", must_use_resource_ty()),
1336 ("TypestateSound", typestate_sound_ty()),
1337 ("Region", region_ty()),
1338 ("RegionAnnotation", region_annotation_ty()),
1339 ("EscapeAnalysis", escape_analysis_ty()),
1340 ("RegionInference", region_inference_ty()),
1341 ("Escape_Sound", escape_sound_ty()),
1342 ("RegionSubtyping", region_subtyping_ty()),
1343 ("MonadicEffect", monadic_effect_ty()),
1344 ("GradedMonad", graded_monad_ty()),
1345 ("CapabilitySet", capability_set_ty()),
1346 ("CapabilityJudgment", capability_judgment_ty()),
1347 ("EffectPolymorphism", effect_polymorphism_ty()),
1348 ("AlgebraicEffectHandler", algebraic_effect_handler_ty()),
1349 ("GradualType", gradual_type_ty()),
1350 ("UnknownType", unknown_type_ty()),
1351 ("ConsistencyRel", consistency_rel_ty()),
1352 ("CastInsertion", cast_insertion_ty()),
1353 ("CastCorrectness", cast_correctness_ty()),
1354 ("Blame_Theorem", blame_theorem_ty()),
1355 ("LiquidType", liquid_type_ty()),
1356 ("QualifierInstantiation", qualifier_instantiation_ty()),
1357 ("SubtypingRefinement", subtyping_refinement_ty()),
1358 ("RefinementInference", refinement_inference_ty()),
1359 ("LiquidType_Complete", liquid_type_complete_ty()),
1360 ("SecurityLabel", security_label_ty()),
1361 ("SecrecyLattice", secrecy_lattice_ty()),
1362 ("LabelEnv", label_env_ty()),
1363 ("NonInterference", non_interference_ty()),
1364 ("Declassification", declassification_ty()),
1365 ("IFCTypeSystem", ifc_type_system_ty()),
1366 ("NI_Theorem", ni_theorem_ty()),
1367 ("ConstantFolding", constant_folding_ty()),
1368 ("ConstantPropagation", constant_propagation_ty()),
1369 ("ConstFold_Correct", const_fold_correct_ty()),
1370 ("IntervalDomain", interval_domain_ty()),
1371 ("BitfieldDomain", bitfield_domain_ty()),
1372 ("ValueRangeAnalysis", value_range_analysis_ty()),
1373 ("VRA_Sound", vra_sound_ty()),
1374 ("NullabilityAnnotation", nullability_annotation_ty()),
1375 ("NullPointerAnalysis", null_pointer_analysis_ty()),
1376 ("DefiniteAssignment", definite_assignment_ty()),
1377 ("NullSafety", null_safety_ty()),
1378 ("NullAnalysis_Sound", null_analysis_sound_ty()),
1379 ("LockOrder", lock_order_ty()),
1380 ("DeadlockFreedom", deadlock_freedom_ty()),
1381 ("LockOrder_Acyclic", lock_order_acyclic_ty()),
1382 ("AtomicBlock", atomic_block_ty()),
1383 ("Atomicity_Serializability", atomicity_serializability_ty()),
1384 ("LockSetAnalysis", lock_set_analysis_ty()),
1385 ("OwnershipType", ownership_type_ty()),
1386 ("BorrowKind", borrow_kind_ty()),
1387 ("Lifetime", lifetime_ty()),
1388 ("BorrowCheck", borrow_check_ty()),
1389 ("OwnershipUnique", ownership_unique_ty()),
1390 ("BorrowCheck_MemSafe", borrow_check_mem_safe_ty()),
1391 ("LifetimeSubtyping", lifetime_subtyping_ty()),
1392 ("NonLexicalLifetime", non_lexical_lifetime_ty()),
1393 ("DataDependence", data_dependence_ty()),
1394 ("ControlDependence", control_dependence_ty()),
1395 ("ProgramDependenceGraph", program_dependence_graph_ty()),
1396 ("BackwardSlice", backward_slice_ty()),
1397 ("ForwardSlice", forward_slice_ty()),
1398 ("Slice_Correct", slice_correct_ty()),
1399 ];
1400 for (name, ty) in axioms {
1401 env.add(Declaration::Axiom {
1402 name: Name::str(*name),
1403 univ_params: vec![],
1404 ty: ty.clone(),
1405 })
1406 .ok();
1407 }
1408 env
1409}
1410#[cfg(test)]
1411mod tests {
1412 use super::*;
1413 #[test]
1415 fn test_build_env_nonempty() {
1416 let env = build_static_analysis_env();
1417 let names = [
1418 "Lattice",
1419 "GaloisConnection",
1420 "Widening",
1421 "Narrowing",
1422 "AndersenAnalysis",
1423 "HappensBefore",
1424 "TaintPropagation",
1425 "ShapeDescriptor",
1426 "KCFA",
1427 "DataRaceFreedom",
1428 ];
1429 let count = names
1430 .iter()
1431 .filter(|&&n| env.get(&Name::str(n)).is_some())
1432 .count();
1433 assert_eq!(count, 10);
1434 }
1435 #[test]
1437 fn test_interval_lattice() {
1438 let a = Interval::Range(1, 5);
1439 let b = Interval::Range(3, 8);
1440 assert_eq!(a.join(&b), Interval::Range(1, 8));
1441 assert_eq!(a.meet(&b), Interval::Range(3, 5));
1442 assert!(Interval::Bottom.leq(&a));
1443 assert!(a.leq(&Interval::top()));
1444 assert!(!b.leq(&a));
1445 }
1446 #[test]
1448 fn test_interval_widening() {
1449 let mut x = Interval::Range(0, 0);
1450 for _ in 0..5 {
1451 let next = x.add(&Interval::single(1));
1452 x = x.widen(&next);
1453 }
1454 assert_eq!(x, Interval::Range(0, i64::MAX));
1455 }
1456 #[test]
1458 fn test_sign_domain() {
1459 assert_eq!(Sign::of(3), Sign::Pos);
1460 assert_eq!(Sign::of(-2), Sign::Neg);
1461 assert_eq!(Sign::of(0), Sign::Zero);
1462 assert_eq!(Sign::Pos.join(&Sign::Neg), Sign::Top);
1463 assert_eq!(Sign::Pos.add(&Sign::Zero), Sign::Pos);
1464 assert_eq!(Sign::Neg.neg(), Sign::Pos);
1465 }
1466 #[test]
1468 fn test_andersen_copy_chain() {
1469 let mut pta = AndersenPTA::new(3);
1470 pta.add_alloc(0, 0);
1471 pta.add_copy(0, 1);
1472 pta.add_copy(1, 2);
1473 pta.solve();
1474 assert!(pta.pts[0].contains(&0));
1475 assert!(pta.pts[1].contains(&0));
1476 assert!(pta.pts[2].contains(&0));
1477 assert!(pta.may_alias(0, 1));
1478 assert!(pta.may_alias(1, 2));
1479 }
1480 #[test]
1482 fn test_taint_propagation() {
1483 let mut ts = TaintState::new();
1484 ts.add_source("user_input");
1485 ts.propagate("x", &["user_input"]);
1486 ts.propagate("y", &["x", "const"]);
1487 assert!(ts.violates("x"));
1488 assert!(ts.violates("y"));
1489 ts.sanitize("x");
1490 assert!(!ts.violates("x"));
1491 assert!(ts.violates("y"));
1492 }
1493 #[test]
1495 fn test_eraser_race_detected() {
1496 let mut state = EraserState::new();
1497 let locks_t1: BTreeSet<usize> = vec![1].into_iter().collect();
1498 let locks_t2: BTreeSet<usize> = vec![2].into_iter().collect();
1499 state.observe_access(0, &locks_t1, true);
1500 state.observe_access(1, &locks_t2, true);
1501 assert!(state.has_race());
1502 }
1503 #[test]
1505 fn test_eraser_no_race() {
1506 let mut state = EraserState::new();
1507 let locks: BTreeSet<usize> = vec![42].into_iter().collect();
1508 state.observe_access(0, &locks, true);
1509 state.observe_access(1, &locks, false);
1510 assert!(!state.has_race());
1511 }
1512 #[test]
1514 fn test_fixpoint_reachability() {
1515 let edges = vec![vec![1], vec![2], vec![]];
1516 let mut solver = FixpointSolver::new(
1517 3,
1518 edges,
1519 false,
1520 |a: &bool, b: &bool| *a || *b,
1521 |n, v| if n == 0 { true } else { *v },
1522 );
1523 solver.values[0] = true;
1524 solver.solve();
1525 assert!(solver.values[1]);
1526 assert!(solver.values[2]);
1527 }
1528 #[test]
1530 fn test_new_axioms_registered() {
1531 let env = build_static_analysis_env();
1532 let names = [
1533 "SepConj",
1534 "FrameRule",
1535 "TypestateSound",
1536 "EscapeAnalysis",
1537 "GradedMonad",
1538 "CastCorrectness",
1539 "LiquidType",
1540 "NonInterference",
1541 "ConstantFolding",
1542 "NullSafety",
1543 "DeadlockFreedom",
1544 "BorrowCheck",
1545 "BackwardSlice",
1546 ];
1547 let count = names
1548 .iter()
1549 .filter(|&&n| env.get(&Name::str(n)).is_some())
1550 .count();
1551 assert_eq!(count, names.len());
1552 }
1553 #[test]
1555 fn test_typestate_automaton_file() {
1556 let mut aut = TypestateAutomaton::new(2, 0);
1557 aut.add_transition(0, "open", 1);
1558 aut.add_transition(1, "read", 1);
1559 aut.add_transition(1, "close", 0);
1560 aut.set_accepting(0);
1561 assert!(aut.accepts(&["open", "read", "close"]));
1562 assert!(!aut.accepts(&["open", "read"]));
1563 assert!(aut.violates(&["open", "open"]));
1564 }
1565 #[test]
1567 fn test_ifc_tracker_violation() {
1568 let mut tracker = IFCTracker::new();
1569 tracker.assign("password", SecurityLevel::High);
1570 tracker.assign("user_id", SecurityLevel::Low);
1571 tracker.propagate("derived", &["password", "user_id"]);
1572 assert_eq!(tracker.label_of("derived"), SecurityLevel::High);
1573 tracker.check_flow("derived", &SecurityLevel::Low);
1574 assert!(tracker.has_violation());
1575 }
1576 #[test]
1578 fn test_ifc_tracker_ok() {
1579 let mut tracker = IFCTracker::new();
1580 tracker.assign("public_id", SecurityLevel::Low);
1581 tracker.check_flow("public_id", &SecurityLevel::High);
1582 assert!(!tracker.has_violation());
1583 }
1584 #[test]
1586 fn test_const_prop_state() {
1587 let mut s1 = ConstPropState::new();
1588 s1.set_const("x", 10);
1589 s1.set_const("y", 5);
1590 assert_eq!(s1.fold_add("x", "y"), Some(15));
1591 let mut s2 = ConstPropState::new();
1592 s2.set_const("x", 10);
1593 s2.set_top("y");
1594 let joined = s1.join(&s2);
1595 assert_eq!(joined.get("x"), Some(10));
1596 assert_eq!(joined.get("y"), None);
1597 }
1598 #[test]
1600 fn test_pd_graph_slicing() {
1601 let mut pdg = PDGraph::new(4);
1602 pdg.add_data_edge(0, 1);
1603 pdg.add_data_edge(1, 3);
1604 let bwd = pdg.backward_slice(3);
1605 assert!(bwd.contains(&3));
1606 assert!(bwd.contains(&1));
1607 assert!(bwd.contains(&0));
1608 assert!(!bwd.contains(&2));
1609 let fwd = pdg.forward_slice(0);
1610 assert!(fwd.contains(&0));
1611 assert!(fwd.contains(&1));
1612 assert!(fwd.contains(&3));
1613 }
1614 #[test]
1616 fn test_null_tracker_alarm() {
1617 let mut tracker = NullTracker::new();
1618 tracker.declare_maybe_null("ptr");
1619 tracker.dereference("ptr");
1620 assert!(tracker.has_alarm());
1621 }
1622 #[test]
1624 fn test_null_tracker_no_alarm() {
1625 let mut tracker = NullTracker::new();
1626 tracker.declare_non_null("safe_ptr");
1627 tracker.dereference("safe_ptr");
1628 assert!(!tracker.has_alarm());
1629 }
1630 #[test]
1632 fn test_null_tracker_join() {
1633 let mut t1 = NullTracker::new();
1634 t1.declare_non_null("p");
1635 let mut t2 = NullTracker::new();
1636 t2.declare_null("p");
1637 let merged = t1.join(&t2);
1638 assert_eq!(merged.get("p"), &Nullability::MaybeNull);
1639 }
1640}