123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282(****************************************************************************)(* *)(* This file is part of MOPSA, a Modular Open Platform for Static Analysis. *)(* *)(* Copyright (C) 2017-2019 The MOPSA Project. *)(* *)(* This program is free software: you can redistribute it and/or modify *)(* it under the terms of the GNU Lesser General Public License as published *)(* by the Free Software Foundation, either version 3 of the License, or *)(* (at your option) any later version. *)(* *)(* This program is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* You should have received a copy of the GNU Lesser General Public License *)(* along with this program. If not, see <http://www.gnu.org/licenses/>. *)(* *)(****************************************************************************)(** Finite powerset of integer constants *)openMopsaopenSig.Abstraction.Simplified_valueopenAstopenTopopenCommonmoduleValue=struct(** {2 Types} *)(** ********* *)modulePowerset=Framework.Lattices.Powerset.Make(structtypet=Z.tletcompare=Z.compareletprint=unformatZ.pp_printend)includePowersetincludeGenValueId(structtypenonrect=tletname="universal.numeric.values.powersets.standard"letdisplay="powerset"end)(** {2 Options} *)(** *********** *)letopt_max_intset=ref10let()=register_domain_optionname{key="-max-set-size";category="Numeric";doc=" maximum size of integer sets";spec=Set_int(opt_max_intset,ArgExt.empty);default=string_of_int!opt_max_intset;}(** {2 Utilities} *)(** ************* *)(* ensures that x is not too large *)letbound(x:t):t=matchxwith|NtswhenSet.cardinals<=!opt_max_intset->x|_->TOP(* add 1 if t is true, 0 if f is true *)letof_booltf=matcht,fwith|false,false->bottom|true,false->singletonZ.one|>bound|false,true->singletonZ.zero|>bound|true,true->of_list[Z.zero;Z.one]|>bound(* [l;h] *)letof_bounds(l:Z.t)(h:Z.t):t=letrecdoitacci=ifi>hthenNtaccelsedoit(Set.addiacc)(Z.succi)inifZ.subhl>=Z.of_int!opt_max_intsetthentopelsedoitSet.emptylletzero=singletonZ.zeroletis_zerox=equalx(singletonZ.zero)letcontains_zeroa=memZ.zeroaletcontains_nonzeroa=not(is_empty(removeZ.zeroa))letto_itv(a:t):int_itv=ifis_bottomathenBOTelsematchawith|Nts->Nb(I.of_z(Set.min_elts)(Set.max_elts))|TOP->NbI.minf_inf(** {2 Forward operators} *)(** ********************* *)includeDefaultValueFunctionsletaccept_type=function|T_int|T_bool->true|_->falseletconstantct=matchcwith|C_booltrue->singletonZ.one|>bound|C_boolfalse->singletonZ.zero|>bound|C_topT_bool->of_boundsZ.zeroZ.one|>bound|C_intn->singletonn|>bound|C_int_interval(ItvUtils.IntBound.Finitei1,ItvUtils.IntBound.Finitei2)->of_boundsi1i2|_->TOPletunopoptatr=matchopwith|O_plus->a|O_minus->mapZ.nega|O_log_not->of_bool(contains_zeroa)(contains_nonzeroa)|O_bit_invert->mapZ.lognota|_->top(* utility for binary operators *)letmap2fa1a2=ifis_topa1||is_topa2thenTOPelsefold(funn1acc->fold(funn2acc->add(fn1n2)acc)a2acc)a1empty|>boundletbinopopt1a1t2a2tr=ifis_bottoma1||is_bottoma2thenbottomelseifis_topa1||is_topa2thentopelseletwith_intfab=fa(Z.to_intb)intrymatchopwith|O_plus->map2Z.adda1a2|O_minus->map2Z.suba1a2|O_mult->ifis_zeroa1||is_zeroa2thenzeroelsemap2Z.mula1a2|O_div->ifis_zeroa1thenzeroelsemap2Z.diva1(removeZ.zeroa2)|O_mod->ifis_zeroa1thenzeroelsemap2Z.rema1(removeZ.zeroa2)|O_pow->map2(with_intZ.pow)a1a2|O_bit_and->map2Z.loganda1a2|O_bit_or->map2Z.logora1a2|O_bit_xor->map2Z.logxora1a2|O_bit_lshift->ifis_zeroa1thenzeroelsemap2(with_intZ.shift_left)a1a2|O_bit_rshift->ifis_zeroa1thenzeroelsemap2(with_intZ.shift_right)a1a2|O_log_or->of_bool(contains_nonzeroa1||contains_nonzeroa2)(contains_zeroa1&&contains_zeroa2)|O_log_and->of_bool(contains_nonzeroa1&&contains_nonzeroa2)(contains_zeroa1||contains_zeroa2)|O_log_xor->of_bool((contains_nonzeroa1&&contains_zeroa2)||(contains_zeroa1&&contains_nonzeroa2))((contains_zeroa1&&contains_zeroa2)||(contains_nonzeroa1&&contains_nonzeroa2))|_->topwithZ.Overflow->TOPletjoin(a1:t)(a2:t):t=Powerset.joina1a2|>boundletwidenctx(a1:t)(a2:t):t=(*if subset a2 a1 then a1 else TOP*)joina1a2(** {2 Backward operators} *)(** ********************** *)letfilterbta=ifbthenremoveZ.zeroaelsemeeta(singletonZ.zero)letavalue:typer.ravalue_kind->t->roption=funavala->matchavalwith|Common.V_int_interval->Some(to_itva)|Common.V_int_interval_fast->Some(to_itva)|Common.V_int_congr_interval->Some(to_itva,Bot.NbCommon.C.minf_inf)|_->Noneletbackward_unopoptatrr=matchopwith|O_plus->meetar|O_minus->meeta(mapZ.negr)|O_bit_invert->meeta(mapZ.lognotr)|_->default_backward_unopoptatrrletbackward_binopopt1a1t2a2trr=letb1,b2=matchopwith|O_plus->meeta1(map2Z.subra2),meeta2(map2Z.subra1)|O_minus->meeta1(map2Z.adda2r),meeta2(map2Z.suba1r)|O_mult->ifcontains_zeroa1||contains_zeroa2thena1,a2elsemeeta1(map2Z.divra2),meeta2(map2Z.divra1)|_->(* TODO: support precisely other operators *)default_backward_binopopt1a1t2a2trrinifis_emptyb1||is_emptyb2thenbottom,bottomelseb1,b2(** {2 Comparisons} *)(** *************** *)(* utility for compare *)letfilta1cmpminmaxa2=matcha2with|TOP->a1|Ntb2->letm=minmaxb2inPowerset.filter(funn->cmpnm)a1letcompareopbt1a1t2a2=letop=ifbthenopelsenegate_comparison_opopinletb1,b2=matchopwith|O_eq->leta=meeta1a2ina,a|O_ne->leta1=ifis_singletona2thendiffa1a2elsea1inleta2=ifis_singletona1thendiffa2a1elsea2ina1,a2|O_le->filta1Z.leqSet.max_elta2,filta2Z.geqSet.min_elta1|O_ge->filta1Z.geqSet.min_elta2,filta2Z.leqSet.max_elta1|O_lt->filta1Z.ltSet.max_elta2,filta2Z.gtSet.min_elta1|O_gt->filta1Z.gtSet.min_elta2,filta2Z.ltSet.max_elta1|_->default_compareopbt1a1t2a2inifis_emptyb1||is_emptyb2thenbottom,bottomelseb1,b2endlet()=register_simplified_value_abstraction(moduleValue)