123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313(**************************************************************************)(* *)(* This file is part of Frama-C. *)(* *)(* Copyright (C) 2007-2023 *)(* CEA (Commissariat à l'énergie atomique et aux énergies *)(* alternatives) *)(* *)(* 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, version 2.1. *)(* *)(* It 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. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file licenses/LGPLv2.1). *)(* *)(**************************************************************************)openCilopenCil_typesopenCil_constopenLogic_constletptr_oft=TPtr(t,[])letconst_oft=Cil.typeAddAttributes[Attr("const",[])]tletsize_t()=Globals.Types.find_typeLogic_typing.Typedef"size_t"letprepare_definitionnamefun_type=letvi=Cil.makeGlobalVar~referenced:truenamefun_typeinvi.vdefined<-true;letfd=Cil.emptyFunctionFromVIviinCil.setFormalsDeclvifun_type;fd.sformals<-Cil.getFormalsDeclvi;fdletcall_functionlvalviargs=letloc=Cil_datatype.Location.unknowninlet_,typs,_,_=Cil.splitFunctionTypeVIviinlettyps=Cil.argsToListtypsinletgen_argexp(_,typ,_)=ifCil_datatype.Typ.equalvi.vtypetypthenexpelseCil.mkCast~newt:typexpinletargs=List.map2gen_argargstypsinCall(lval,(Cil.evarvi),args,loc)letrecstring_of_typ_aux=function|TVoid(_)->"void"|TInt(IBool,_)->"bool"|TInt(IChar,_)->"char"|TInt(ISChar,_)->"schar"|TInt(IUChar,_)->"uchar"|TInt(IInt,_)->"int"|TInt(IUInt,_)->"uint"|TInt(IShort,_)->"short"|TInt(IUShort,_)->"ushort"|TInt(ILong,_)->"long"|TInt(IULong,_)->"ulong"|TInt(ILongLong,_)->"llong"|TInt(IULongLong,_)->"ullong"|TFloat(FFloat,_)->"float"|TFloat(FDouble,_)->"double"|TFloat(FLongDouble,_)->"ldouble"|TPtr(t,_)->"ptr_"^string_of_typt|TEnum(ei,_)->"e_"^ei.ename|TComp(ci,_)whenci.cstruct->"st_"^ci.cname|TComp(ci,_)->"un_"^ci.cname|TArray(t,Somee,_)->"arr"^(string_of_expe)^"_"^string_of_typt|t->Options.fatal"unsupported type %a"Cil_printer.pp_typtandstring_of_typt=string_of_typ_aux(Cil.unrollTypet)andstring_of_expe=Format.asprintf"%a"Cil_printer.pp_expeletsize_var?(name_ext="")tvalue={l_var_info=make_logic_var_local("__fc_"^name_ext^"len")t;l_type=Somet;l_tparams=[];l_labels=[];l_profile=[];l_body=LBtermvalue;}(** Features related to terms *)letcvar_to_tvarvi=tvar(cvar_to_lvarvi)lettminus?loct1t2=letminus,typ=matcht1.term_type,t2.term_typewith|Ctype(t1),Ctype(t2)whenCil.isPointerTypet1&&Cil.isPointerTypet2->MinusPP,Linteger|Ctype(t),_whenCil.isPointerTypet->MinusPI,Ctype(t)|t,_->MinusA,tinterm?loc(TBinOp(minus,t1,t2))typlettplus?loct1t2=letplus=matcht1.term_typewith|Ctype(t)whenCil.isPointerTypet->PlusPI|_->PlusAinterm?loc(TBinOp(plus,t1,t2))t1.term_typelettdivide?loct1t2=term?loc(TBinOp(Div,t1,t2))t1.term_typeletttype_of_pointedt=matchLogic_utils.unroll_typetwith|Ctype(TPtr(t,_))|Ctype(TArray(t,_,_))->Ctypet|_->Options.fatal"ttype_of_pointed on a non pointer type"lettbuffer_range?locptrlen=letlast=tminus?loclen(tinteger?loc1)inletrange=trange?loc(Some(tinteger?loc0),Somelast)intplus?locptrrangeletrectunref_range?locptrlen=lettyp=ttype_of_pointedptr.term_typeinletrange=tbuffer_range?locptrleninlettlval=(TMemrange),TNoOffsetinlettlval,typ=tunref_range_unfold?loctlvaltypinterm(TLvaltlval)typandtunref_range_unfold?loclvaltyp=matchtypwith|Ctype(TArray(typ,Somee,_))->letlen=Logic_utils.expr_to_term~coerce:trueeinletlast=tminus?loclen(tinteger?loc1)inletrange=trange?loc(Some(tinteger?loc0),Somelast)inletlval=addTermOffsetLval(TIndex(range,TNoOffset))lvalintunref_range_unfoldlval(Ctypetyp)|_->lval,typlettaccess?locptroffset=letget_lval=function|TLval(lval)->lval|_->Options.fatal"unexpected non-lvalue on call to taccess"inmatchLogic_utils.unroll_typeptr.term_typewith|Ctype(TPtr(_))->letaddress=tplus?locptroffsetinletlval=TLval(TMem(address),TNoOffset)interm?loclval(ttype_of_pointedptr.term_type)|Ctype(TArray(_))->letlval=get_lvalptr.term_nodeinletlval=addTermOffsetLval(TIndex(offset,TNoOffset))lvalinterm?loc(TLvallval)(ttype_of_pointedptr.term_type)|_->Options.fatal"taccess on a non pointer type"letsizeofpointed=function|Ctype(TPtr(t,_))|Ctype(TArray(t,_,_))->Cil.bytesSizeOft|_->Options.fatal"size_of_pointed on a non pointer type"letsizeof=function|Ctypet->Cil.bytesSizeOft|_->Options.fatal"sizeof on a non C type"lettunref_range_bytes_len?locptrbytes_len=letsizeof=sizeofpointedptr.term_typeinifsizeof=1thentunref_range?locptrbytes_lenelseletsizeof=tinteger?locsizeofinletlen=tdivide?locbytes_lensizeofintunref_range?locptrlen(** Features related to predicates *)letplet_len_div_size?loc?name_exttbytes_lenpred=letsizeof=sizeofpointedtinifsizeof=1thenpredbytes_lenelseletlen=tdivide?locbytes_len(tinteger?locsizeof)inletlen_var=size_var?name_extLintegerleninplet?loclen_var(pred(tvarlen_var.l_var_info))letpgeneric_valid_buffer?locvaliditylblptrlen=letbuffer=tbuffer_range?locptrleninvalidity?loc(lbl,buffer)letpgeneric_valid_len_bytes?locvaliditylblptrbytes_len=plet_len_div_size?locptr.term_typebytes_len(pgeneric_valid_buffer?locvaliditylblptr)letpvalid_len_bytes?loc=pgeneric_valid_len_bytes?locpvalidletpvalid_read_len_bytes?loc=pgeneric_valid_len_bytes?locpvalid_readletpcorrect_len_bytes?loctbytes_len=letsizeof=tinteger?loc(sizeofpointedt)inletmodulo=term?loc(TBinOp(Mod,bytes_len,sizeof))Lintegerinprel?loc(Req,modulo,tinteger?loc0)letpbounds_incl_excl?loclowvalueup=letgeq_0=prel?loc(Rle,low,value)inletlt_len=prel?loc(Rlt,value,up)inpand?loc(geq_0,lt_len)letrecpunfold_all_elems_eq?loct1t2len=assert(Cil_datatype.Logic_type.equalt1.term_typet2.term_type);pall_elems_eq?loc0t1t2lenandpall_elems_eq?locdeptht1t2len=letind=make_logic_var_quant("j"^(string_of_intdepth))Lintegerinlettind=tvarindinletbounds=pbounds_incl_excl?loc(tinteger0)tindleninlett1_acc=taccess?loct1tindinlett2_acc=taccess?loct2tindinleteq=peq_unfold?loc(depth+1)t1_acct2_accinpforall?loc([ind],(pimplies?loc(bounds,eq)))andpeq_unfold?locdeptht1t2=matchLogic_utils.unroll_typet1.term_typewith|Ctype(TArray(_,Somelen,_))->letlen=Logic_utils.expr_to_term~coerce:trueleninpall_elems_eq?locdeptht1t2len|_->prel?loc(Req,t1,t2)letrecpunfold_all_elems_pred?loct1lenpred=pall_elems_pred?loc0t1lenpredandpall_elems_pred?locdeptht1lenpred=letind=make_logic_var_quant("j"^(string_of_intdepth))Lintegerinlettind=tvarindinletbounds=pbounds_incl_excl?loc(tinteger0)tindleninlett1_acc=taccess?loct1tindinleteq=punfold_pred?locdeptht1_accpredinpforall?loc([ind],(pimplies?loc(bounds,eq)))andpunfold_pred?loc?(dyn_len=None)deptht1pred=matchLogic_utils.unroll_typet1.term_typewith|Ctype(TArray(_,opt_len,_))->letlen=matchopt_len,dyn_lenwith|Somelen,None->Logic_utils.expr_to_term~coerce:truelen|_,Somelen->len|None,None->Options.fatal"Unfolding array: cannot find a length"inpall_elems_pred?loc(depth+1)t1lenpred|Ctype(TComp(ci,_))->pall_fields_pred?locdeptht1cipred|_->pred?loct1andpall_fields_pred?loc?(flex_mem_len=None)deptht1cipred=leteqdyn_lenfi=letlval=matcht1.term_nodewithTLval(lv)->lv|_->assertfalseinletnlval=addTermOffsetLval(TField(fi,TNoOffset))lvalinletterm=term?loc(TLvalnlval)(Ctypefi.ftype)inpunfold_pred?loc~dyn_lendepthtermpredinletreceqs_fields=function|[]->[]|[x]->[eqflex_mem_lenx]|x::l->letx'=eqNonexinx'::(eqs_fieldsl)inpands(eqs_fields(Option.getci.cfields))letpunfold_flexible_struct_pred?locthe_structbytes_lenpred=letstruct_len=tinteger?loc(sizeofthe_struct.term_type)inletci=matchthe_struct.term_typewith|Ctype(TComp(ci,_)ast)whenCil.has_flexible_array_membert->ci|_->Options.fatal"Unfolding flexible on a non flexible structure"inletflex_type=Ctype(Extlib.last(Option.getci.cfields)).ftypeinletflex_len=tminusbytes_lenstruct_leninletpall_fields_predlen=pall_fields_pred?loc~flex_mem_len:(Somelen)0the_structcipredinplet_len_div_size?loc~name_ext:"flex"flex_typeflex_lenpall_fields_predletpseparated_memories?locp1len1p2len2=letb1=tbuffer_range?locp1len1inletb2=tbuffer_range?locp2len2inpseparated?loc[b1;b2]letmake_behavior?(name=Cil.default_behavior_name)?(assumes=[])?(requires=[])?(ensures=[])?(assigns=WritesAny)?(alloc=FreeAllocAny)?(extension=[])()={b_name=name;b_requires=requires;b_assumes=assumes;b_post_cond=ensures;b_assigns=assigns;b_allocation=alloc;b_extended=extension}letdefault_comp_disjbhvs=letb_names=List.filter(funb->not(String.equalCil.default_behavior_nameb))(List.fold_left(funlb->b.b_name::l)[]bhvs)inmatchb_nameswith|[]->[],[]|_->[b_names],[b_names]letmake_funspecbhvs?(termination=None)?(complete_disjoint=(default_comp_disjbhvs))()=letcomplete,disjoint=complete_disjointin{spec_behavior=bhvs;spec_variant=None;spec_terminates=termination;spec_complete_behaviors=complete;spec_disjoint_behaviors=disjoint}