From: oleg@okmij.org
To: David.Teller@ens-lyon.org
Cc: caml-list@inria.fr
Subject: Re: Keeping local types local?
Date: Wed, 17 Sep 2008 01:07:50 -0700 (PDT) [thread overview]
Message-ID: <20080917080750.6625AAE54@Adric.metnet.fnmoc.navy.mil> (raw)
In-Reply-To: <1221583622.6350.178.camel@Blefuscu>
> So I'm looking for another way out. As far as both your examples and my
> experiments seem to indicate, the only way of escaping scope is to
> return a continuation which calls one of the protected functions and
> ignores the result.
I'm afraid this is worse than it seems. Returning any closure (not
necessarily a continuation) can defeat the security. To summarize, the
security of the framework is defeated if
-- one returns a closure that calls a protected function
-- one returns an object whose method calls a protected function
-- one returns a polymorphic record that `abstracts'
over the abstract type guarding the protected function
-- one assigns to the mutable variable: a closure, an object,
or a polymorphic record
-- one throws or returns an exception that contains a closure,
an object, or a polymorphic record
Here is the illustrating code. We start with the baseline
let f0 () =
let result =
let module A =
struct
type 'a t = Guard of 'a (*Used only to prevent scope escape.*)
(** Local primitives, usage guarded by [Guard] *)
let set v =
print_endline "set has been called"; Guard ()
let return x = Guard x
let result =
print_endline "Initialization";
match
(* Good client *)
set 1
with Guard x -> print_endline "Clean-up"; x
end in A.result
in result
;;
let test1 = f0 ();;
We see that set has been called after initialization and _before_ the
clean-up. In the code below, we replace the client line (which above
was just `set 1') with something else. The stupid bad client
let f1 () = ...
return (fun () -> set 1)
...
is easily caught. The type checker rejects the code with the message
This `let module' expression has type unit -> unit A.t
In this type, the locally bound module name A escapes its scope
Alas, a bit more cunning client, as you have observed,
let f2 () = ...
return (fun () -> ignore (set 1); ())
...
let test2 = f2 () ();;
manages to call the setter _after_ the clean-up. But that is not the
only cunning client. Here is another one
let f3 () = ...
return (object val mutable guarded = return ()
method call_setter = guarded <- set ()
end)
...
let test3 = (f3 ())#call_setter;;
and another one
exception Foo of (unit -> unit);;
let f4 () = ...
return (Foo (fun () -> ignore (set 1); ()))
let test4 = try raise (f4 ()) with Foo e -> e ();;
and another one
let cunning_ref = ref (fun () -> ())
let f5 () = ...
cunning_ref := (fun () -> ignore (set 1); ()); return ()
...
let test5 = f5 (); !cunning_ref ();;
To ensure security, one should prohibit returning, assigning or
throwing any values other than the values of simple types: numbers,
strings, pairs, arrays and lists of those. In short, only easily
serializable values may be returned, assigned and thrown.
I fully agree with your assessment of monads. I should remark that
type-based assurances work well for data dependencies, but not so for
control dependencies (that's why we need a so-called type-state).
Monads convert control dependency into data dependency.
You do know of FlowCaml, right? It doesn't seem to be actively
maintained though...
next prev parent reply other threads:[~2008-09-17 8:09 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-09-16 10:12 oleg
2008-09-16 16:47 ` David Rajchenbach-Teller
2008-09-17 8:07 ` oleg [this message]
2008-09-19 13:55 ` [Caml-list] " David Rajchenbach-Teller
-- strict thread matches above, loose matches on Subject: below --
2008-09-18 23:34 oleg
2008-09-15 12:37 David Rajchenbach-Teller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080917080750.6625AAE54@Adric.metnet.fnmoc.navy.mil \
--to=oleg@okmij.org \
--cc=David.Teller@ens-lyon.org \
--cc=caml-list@inria.fr \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox