From 106a7c4a86e4c164a73cbc5a4c14f3c4ff527f30 Mon Sep 17 00:00:00 2001 From: Pierre-Marie Pédrot Date: Sun, 12 May 2019 23:43:01 +0200 Subject: Reduce the attack surface of Opaqueproof. --- kernel/modops.ml | 6 +----- kernel/opaqueproof.ml | 29 +++++++++-------------------- kernel/opaqueproof.mli | 4 +--- 3 files changed, 11 insertions(+), 28 deletions(-) (limited to 'kernel') diff --git a/kernel/modops.ml b/kernel/modops.ml index 4f992d3972..4fdd7ab334 100644 --- a/kernel/modops.ml +++ b/kernel/modops.ml @@ -608,11 +608,7 @@ let clean_bounded_mod_expr sign = (** {6 Stm machinery } *) let join_constant_body except otab cb = match cb.const_body with - | OpaqueDef o -> - (match Opaqueproof.uuid_opaque otab o with - | Some uuid when not(Future.UUIDSet.mem uuid except) -> - Opaqueproof.join_opaque otab o - | _ -> ()) + | OpaqueDef o -> Opaqueproof.join_opaque ~except otab o | _ -> () let join_structure except otab s = diff --git a/kernel/opaqueproof.ml b/kernel/opaqueproof.ml index 303cb06c55..57059300b8 100644 --- a/kernel/opaqueproof.ml +++ b/kernel/opaqueproof.ml @@ -87,19 +87,18 @@ let discharge_direct_opaque ~cook_constr ci = function | Direct (d,cu) -> Direct (ci::d,Future.chain cu (fun (c, u) -> cook_constr c, u)) -let join_opaque { opaque_val = prfs; opaque_dir = odp; _ } = function - | Direct (_,cu) -> ignore(Future.join cu) +let join except cu = match except with +| None -> ignore (Future.join cu) +| Some except -> + if Future.UUIDSet.mem (Future.uuid cu) except then () + else ignore (Future.join cu) + +let join_opaque ?except { opaque_val = prfs; opaque_dir = odp; _ } = function + | Direct (_,cu) -> join except cu | Indirect (_,dp,i) -> if DirPath.equal dp odp then let fp = snd (Int.Map.find i prfs) in - ignore(Future.join fp) - -let uuid_opaque { opaque_val = prfs; opaque_dir = odp; _ } = function - | Direct (_,cu) -> Some (Future.uuid cu) - | Indirect (_,dp,i) -> - if DirPath.equal dp odp - then Some (Future.uuid (snd (Int.Map.find i prfs))) - else None + join except fp let force_proof { opaque_val = prfs; opaque_dir = odp; _ } = function | Direct (_,cu) -> @@ -128,16 +127,6 @@ let get_constraints { opaque_val = prfs; opaque_dir = odp; _ } = function then Some(Future.chain (snd (Int.Map.find i prfs)) snd) else !get_univ dp i -let get_proof { opaque_val = prfs; opaque_dir = odp; _ } = function - | Direct (_,cu) -> Future.chain cu fst - | Indirect (l,dp,i) -> - let pt = - if DirPath.equal dp odp - then Future.chain (snd (Int.Map.find i prfs)) fst - else !get_opaque dp i in - Future.chain pt (fun c -> - force_constr (List.fold_right subst_substituted l (from_val c))) - module FMap = Future.UUIDMap let a_constr = Future.from_val (mkRel 1) diff --git a/kernel/opaqueproof.mli b/kernel/opaqueproof.mli index 5ea6da649b..d47c0bbb3c 100644 --- a/kernel/opaqueproof.mli +++ b/kernel/opaqueproof.mli @@ -39,7 +39,6 @@ val turn_indirect : DirPath.t -> opaque -> opaquetab -> opaque * opaquetab indirect opaque accessor configured below. *) val force_proof : opaquetab -> opaque -> constr val force_constraints : opaquetab -> opaque -> Univ.ContextSet.t -val get_proof : opaquetab -> opaque -> constr Future.computation val get_constraints : opaquetab -> opaque -> Univ.ContextSet.t Future.computation option @@ -60,8 +59,7 @@ type cooking_info = { val discharge_direct_opaque : cook_constr:(constr -> constr) -> cooking_info -> opaque -> opaque -val uuid_opaque : opaquetab -> opaque -> Future.UUID.t option -val join_opaque : opaquetab -> opaque -> unit +val join_opaque : ?except:Future.UUIDSet.t -> opaquetab -> opaque -> unit val dump : opaquetab -> Constr.t Future.computation array * -- cgit v1.2.3 From e74fce3090323b4d3734f84ee8cf6dc1f5e85953 Mon Sep 17 00:00:00 2001 From: Pierre-Marie Pédrot Date: Mon, 13 May 2019 00:03:36 +0200 Subject: Abstract away the implementation of side-effects in Safe_typing. --- kernel/entries.ml | 14 -------------- kernel/safe_typing.ml | 29 ++++++++++++++++++++++------- kernel/safe_typing.mli | 8 +++----- 3 files changed, 25 insertions(+), 26 deletions(-) (limited to 'kernel') diff --git a/kernel/entries.ml b/kernel/entries.ml index a3d32267a7..adb3f6bd29 100644 --- a/kernel/entries.ml +++ b/kernel/entries.ml @@ -108,21 +108,7 @@ type module_entry = | MExpr of module_params_entry * module_struct_entry * module_struct_entry option - -type seff_env = - [ `Nothing - (* The proof term and its universes. - Same as the constant_body's but not in an ephemeron *) - | `Opaque of Constr.t * Univ.ContextSet.t ] - (** Not used by the kernel. *) type side_effect_role = | Subproof | Schema of inductive * string - -type side_eff = { - seff_constant : Constant.t; - seff_body : Declarations.constant_body; - seff_env : seff_env; - seff_role : side_effect_role; -} diff --git a/kernel/safe_typing.ml b/kernel/safe_typing.ml index 673f025c75..7b573e3146 100644 --- a/kernel/safe_typing.ml +++ b/kernel/safe_typing.ml @@ -228,6 +228,12 @@ let check_engagement env expected_impredicative_set = (** {6 Stm machinery } *) +type seff_env = + [ `Nothing + (* The proof term and its universes. + Same as the constant_body's but not in an ephemeron *) + | `Opaque of Constr.t * Univ.ContextSet.t ] + let get_opaque_body env cbo = match cbo.const_body with | Undef _ -> assert false @@ -238,9 +244,16 @@ let get_opaque_body env cbo = (Opaqueproof.force_proof (Environ.opaque_tables env) opaque, Opaqueproof.force_constraints (Environ.opaque_tables env) opaque) +type side_eff = { + seff_constant : Constant.t; + seff_body : Declarations.constant_body; + seff_env : seff_env; + seff_role : Entries.side_effect_role; +} + type side_effect = { from_env : Declarations.structure_body CEphemeron.key; - eff : Entries.side_eff list; + eff : side_eff list; } module SideEffects : @@ -254,7 +267,6 @@ end = struct module SeffOrd = struct -open Entries type t = side_effect let compare e1 e2 = let cmp e1 e2 = Constant.CanOrd.compare e1.seff_constant e2.seff_constant in @@ -282,6 +294,14 @@ let side_effects_of_private_constants l = let ans = List.rev (SideEffects.repr l) in List.map_append (fun { eff; _ } -> eff) ans +let push_private_constants env eff = + let eff = side_effects_of_private_constants eff in + let add_if_undefined env eff = + try ignore(Environ.lookup_constant eff.seff_constant env); env + with Not_found -> Environ.add_constant eff.seff_constant eff.seff_body env + in + List.fold_left add_if_undefined env eff + let empty_private_constants = SideEffects.empty let add_private mb eff effs = let from_env = CEphemeron.create mb in @@ -289,7 +309,6 @@ let add_private mb eff effs = let concat_private = SideEffects.concat let make_eff env cst r = - let open Entries in let cbo = Environ.lookup_constant cst env.env in { seff_constant = cst; @@ -309,7 +328,6 @@ let private_con_of_scheme ~kind env cl = add_private env.revstruct eff empty_private_constants let universes_of_private eff = - let open Entries in let fold acc eff = let acc = match eff.seff_env with | `Nothing -> acc @@ -588,7 +606,6 @@ let add_constant_aux ~in_section senv (kn, cb) = let mk_pure_proof c = (c, Univ.ContextSet.empty), SideEffects.empty let inline_side_effects env body side_eff = - let open Entries in let open Constr in (** First step: remove the constants that are still in the environment *) let filter { eff = se; from_env = mb } = @@ -725,7 +742,6 @@ let constant_entry_of_side_effect cb u = const_entry_inline_code = cb.const_inline_code } let turn_direct orig = - let open Entries in let cb = orig.seff_body in if Declareops.is_opaque cb then let p = match orig.seff_env with @@ -738,7 +754,6 @@ let turn_direct orig = else orig let export_eff eff = - let open Entries in (eff.seff_constant, eff.seff_body, eff.seff_role) let export_side_effects mb env c = diff --git a/kernel/safe_typing.mli b/kernel/safe_typing.mli index 46c97c1fb8..6fcdef9a10 100644 --- a/kernel/safe_typing.mli +++ b/kernel/safe_typing.mli @@ -43,11 +43,6 @@ type 'a safe_transformer = safe_environment -> 'a * safe_environment type private_constants -val side_effects_of_private_constants : - private_constants -> Entries.side_eff list -(** Return the list of individual side-effects in the order of their - creation. *) - val empty_private_constants : private_constants val concat_private : private_constants -> private_constants -> private_constants (** [concat_private e1 e2] adds the constants of [e1] to [e2], i.e. constants in @@ -62,6 +57,9 @@ val inline_private_constants_in_constr : val inline_private_constants_in_definition_entry : Environ.env -> private_constants Entries.definition_entry -> unit Entries.definition_entry +val push_private_constants : Environ.env -> private_constants -> Environ.env +(** Push the constants in the environment if not already there. *) + val universes_of_private : private_constants -> Univ.ContextSet.t list val is_curmod_library : safe_environment -> bool -- cgit v1.2.3 From 3cdaffab75414f3f59386a4b76c6b00c94bc8b0e Mon Sep 17 00:00:00 2001 From: Pierre-Marie Pédrot Date: Mon, 13 May 2019 00:26:56 +0200 Subject: Simplify the private constant API. We ungroup the rewrite scheme-defined constants, while only exporting a function to turn the last added constant into a private constant. --- kernel/safe_typing.ml | 102 ++++++++++++++++++++----------------------------- kernel/safe_typing.mli | 4 +- 2 files changed, 43 insertions(+), 63 deletions(-) (limited to 'kernel') diff --git a/kernel/safe_typing.ml b/kernel/safe_typing.ml index 7b573e3146..75375812c0 100644 --- a/kernel/safe_typing.ml +++ b/kernel/safe_typing.ml @@ -244,18 +244,14 @@ let get_opaque_body env cbo = (Opaqueproof.force_proof (Environ.opaque_tables env) opaque, Opaqueproof.force_constraints (Environ.opaque_tables env) opaque) -type side_eff = { +type side_effect = { + from_env : Declarations.structure_body CEphemeron.key; seff_constant : Constant.t; seff_body : Declarations.constant_body; seff_env : seff_env; seff_role : Entries.side_effect_role; } -type side_effect = { - from_env : Declarations.structure_body CEphemeron.key; - eff : side_eff list; -} - module SideEffects : sig type t @@ -269,8 +265,7 @@ struct module SeffOrd = struct type t = side_effect let compare e1 e2 = - let cmp e1 e2 = Constant.CanOrd.compare e1.seff_constant e2.seff_constant in - List.compare cmp e1.eff e2.eff + Constant.CanOrd.compare e1.seff_constant e2.seff_constant end module SeffSet = Set.Make(SeffOrd) @@ -291,8 +286,7 @@ end type private_constants = SideEffects.t let side_effects_of_private_constants l = - let ans = List.rev (SideEffects.repr l) in - List.map_append (fun { eff; _ } -> eff) ans + List.rev (SideEffects.repr l) let push_private_constants env eff = let eff = side_effects_of_private_constants eff in @@ -303,29 +297,24 @@ let push_private_constants env eff = List.fold_left add_if_undefined env eff let empty_private_constants = SideEffects.empty -let add_private mb eff effs = - let from_env = CEphemeron.create mb in - SideEffects.add { eff; from_env } effs let concat_private = SideEffects.concat -let make_eff env cst r = +let private_constant env role cst = + (** The constant must be the last entry of the safe environment *) + let () = match env.revstruct with + | (lbl, SFBconst _) :: _ -> assert (Label.equal lbl (Constant.label cst)) + | _ -> assert false + in + let from_env = CEphemeron.create env.revstruct in let cbo = Environ.lookup_constant cst env.env in - { + let eff = { + from_env = from_env; seff_constant = cst; seff_body = cbo; seff_env = get_opaque_body env.env cbo; - seff_role = r; - } - -let private_con_of_con env c = - let open Entries in - let eff = [make_eff env c Subproof] in - add_private env.revstruct eff empty_private_constants - -let private_con_of_scheme ~kind env cl = - let open Entries in - let eff = List.map (fun (i, c) -> make_eff env c (Schema (i, kind))) cl in - add_private env.revstruct eff empty_private_constants + seff_role = role; + } in + SideEffects.add eff empty_private_constants let universes_of_private eff = let fold acc eff = @@ -608,19 +597,15 @@ let mk_pure_proof c = (c, Univ.ContextSet.empty), SideEffects.empty let inline_side_effects env body side_eff = let open Constr in (** First step: remove the constants that are still in the environment *) - let filter { eff = se; from_env = mb } = - let map e = (e.seff_constant, e.seff_body, e.seff_env) in - let cbl = List.map map se in - let not_exists (c,_,_) = - try ignore(Environ.lookup_constant c env); false - with Not_found -> true in - let cbl = List.filter not_exists cbl in - (cbl, mb) + let filter e = + let cb = (e.seff_constant, e.seff_body, e.seff_env) in + try ignore (Environ.lookup_constant e.seff_constant env); None + with Not_found -> Some (cb, e.from_env) in (* CAVEAT: we assure that most recent effects come first *) - let side_eff = List.map filter (SideEffects.repr side_eff) in - let sigs = List.rev_map (fun (cbl, mb) -> mb, List.length cbl) side_eff in - let side_eff = List.fold_left (fun accu (cbl, _) -> cbl @ accu) [] side_eff in + let side_eff = List.map_filter filter (SideEffects.repr side_eff) in + let sigs = List.rev_map (fun (_, mb) -> mb) side_eff in + let side_eff = List.fold_left (fun accu (cb, _) -> cb :: accu) [] side_eff in let side_eff = List.rev side_eff in (** Most recent side-effects first in side_eff *) if List.is_empty side_eff then (body, Univ.ContextSet.empty, sigs) @@ -692,24 +677,22 @@ let inline_private_constants_in_definition_entry env ce = let inline_private_constants_in_constr env body side_eff = pi1 (inline_side_effects env body side_eff) -let rec is_nth_suffix n l suf = - if Int.equal n 0 then l == suf - else match l with - | [] -> false - | _ :: l -> is_nth_suffix (pred n) l suf +let is_suffix l suf = match l with +| [] -> false +| _ :: l -> l == suf (* Given the list of signatures of side effects, checks if they match. * I.e. if they are ordered descendants of the current revstruct. Returns the number of effects that can be trusted. *) let check_signatures curmb sl = - let is_direct_ancestor accu (mb, how_many) = + let is_direct_ancestor accu mb = match accu with | None -> None | Some (n, curmb) -> try let mb = CEphemeron.get mb in - if is_nth_suffix how_many mb curmb - then Some (n + how_many, mb) + if is_suffix mb curmb + then Some (n + 1, mb) else None with CEphemeron.InvalidKey -> None in let sl = List.fold_left is_direct_ancestor (Some (0, curmb)) sl in @@ -766,10 +749,9 @@ let export_side_effects mb env c = let not_exists e = try ignore(Environ.lookup_constant e.seff_constant env); false with Not_found -> true in - let aux (acc,sl) { eff = se; from_env = mb } = - let cbl = List.filter not_exists se in - if List.is_empty cbl then acc, sl - else cbl :: acc, (mb,List.length cbl) :: sl in + let aux (acc,sl) e = + if not (not_exists e) then acc, sl + else e :: acc, e.from_env :: sl in let seff, signatures = List.fold_left aux ([],[]) (SideEffects.repr eff) in let trusted = check_signatures mb signatures in let push_seff env eff = @@ -787,10 +769,9 @@ let export_side_effects mb env c = let rec translate_seff sl seff acc env = match seff with | [] -> List.rev acc, ce - | cbs :: rest -> + | eff :: rest -> if Int.equal sl 0 then - let env, cbs = - List.fold_left (fun (env,cbs) eff -> + let env, cb = let { seff_constant = kn; seff_body = ocb; seff_env = u ; _ } = eff in let ce = constant_entry_of_side_effect ocb u in let cb = Term_typing.translate_constant Term_typing.Pure env kn ce in @@ -798,15 +779,14 @@ let export_side_effects mb env c = seff_body = cb; seff_env = `Nothing; } in - (push_seff env eff, export_eff eff :: cbs)) - (env,[]) cbs in - translate_seff 0 rest (cbs @ acc) env + (push_seff env eff, export_eff eff) + in + translate_seff 0 rest (cb :: acc) env else - let cbs_len = List.length cbs in - let cbs = List.map turn_direct cbs in - let env = List.fold_left push_seff env cbs in - let ecbs = List.map export_eff cbs in - translate_seff (sl - cbs_len) rest (ecbs @ acc) env + let cb = turn_direct eff in + let env = push_seff env cb in + let ecb = export_eff cb in + translate_seff (sl - 1) rest (ecb :: acc) env in translate_seff trusted seff [] env diff --git a/kernel/safe_typing.mli b/kernel/safe_typing.mli index 6fcdef9a10..d6c7022cf5 100644 --- a/kernel/safe_typing.mli +++ b/kernel/safe_typing.mli @@ -48,8 +48,8 @@ val concat_private : private_constants -> private_constants -> private_constants (** [concat_private e1 e2] adds the constants of [e1] to [e2], i.e. constants in [e1] must be more recent than those of [e2]. *) -val private_con_of_con : safe_environment -> Constant.t -> private_constants -val private_con_of_scheme : kind:string -> safe_environment -> (inductive * Constant.t) list -> private_constants +val private_constant : safe_environment -> Entries.side_effect_role -> Constant.t -> private_constants +(** Constant must be the last definition of the safe_environment. *) val mk_pure_proof : Constr.constr -> private_constants Entries.proof_output val inline_private_constants_in_constr : -- cgit v1.2.3