
Since the online lambdabot still doesn't seem to want to talk to me, I've been thinking about how I might rectify the situation... Apparently GHC has a flag that makes it execute a Haskell expression directly. For example, C:\> ghc -e "map (2*) [1,2,3]" [2,4,6] Now, if I could just figure out how to make a web server call GHC... I'm laughing! Oh, but there is the *minor* detail that I am literally allowing unauthenticated users to perform arbitrary code execution. For example, C:\> ghc -e "writeFile \"Test.txt\" \"Hi mum!\"" (Generates a file on my harddrive "Test.txt" containing the text "Hi mum!".) AFAIK, Lambdabot dissalows any expression that performs IO. In Haskell, this is beautifully easy: reject any expression having an IO type. And it seems that GHC accepts not just an *expression*, but a *command*. In particular, this works: C:\> ghc -e ":t writeFile \"Test.txt\" \"Hi mum!\"" writeFile "Test.txt" "Hi mum!" :: IO () However, when you consider that the result type could be "IO ()" or "IO String" or "IO [Either (Maybe Int, (String, Bool)) [Either (Int -> String) (Complex Integer)]]", and the expression itself may well contain the "::" sequence... you see we have a nontrivial parsing task here! (Get the parsing wrong and somebody might be able to do Evil Things to the box.) The other possibility is to somehow run GHC under a user context that doesn't *have* write access to anything on the filesystem. That way there is no margin for error. This leaves only the problem of how to make a web server call GHC. I can think of a number of possibilities. - Write my own HTTP server from scratch. (Not keen...) - Configure Apache to do it. (Is that physically possible?) - Use Apache and some bizzare Perl scripting to do the actual call. (Assuming *that* is possible.) - Use Apache and some Perl scripts to write the data to a text file, and write a small Haskell program to poll the filesystem waiting for request files to appear, run then though GHC, and put the result back into a file. Write another Perl script to slurp up the result and send it back to the caller. - Doesn't Java have a free HTTP server implementation? Maybe I could use that... - ...others? (I'm not sure why this should be, but it seems that Don has made several replies to my emails that didn't show up in my inbox, and only show up on the list archives. Oh well, anyway...) I lurk on the POV-Ray NNTP server, and we recently had quite a discussion about Haskell. I'd *love* to be able to say to people "hey, you don't even need to bother working out how to install GHC, just CLICK THIS LINK and you can play with Haskell instantly!" But at the moment I'm not entirely sure how to set this up. Ideas?

andrewcoppin:
Since the online lambdabot still doesn't seem to want to talk to me, I've been thinking about how I might rectify the situation...
Apparently GHC has a flag that makes it execute a Haskell expression directly. For example,
C:\> ghc -e "map (2*) [1,2,3]" [2,4,6]
Now, if I could just figure out how to make a web server call GHC... I'm laughing!
Oh, but there is the *minor* detail that I am literally allowing unauthenticated users to perform arbitrary code execution. For example,
C:\> ghc -e "writeFile \"Test.txt\" \"Hi mum!\""
(Generates a file on my harddrive "Test.txt" containing the text "Hi mum!".)
AFAIK, Lambdabot dissalows any expression that performs IO. In Haskell, this is beautifully easy: reject any expression having an IO type. And it seems that GHC accepts not just an *expression*, but a *command*. In particular, this works:
C:\> ghc -e ":t writeFile \"Test.txt\" \"Hi mum!\"" writeFile "Test.txt" "Hi mum!" :: IO ()
However, when you consider that the result type could be "IO ()" or "IO String" or "IO [Either (Maybe Int, (String, Bool)) [Either (Int -> String) (Complex Integer)]]", and the expression itself may well contain the "::" sequence... you see we have a nontrivial parsing task here! (Get the parsing wrong and somebody might be able to do Evil Things to the box.)
Don't use parsing for security, use the type checker. By using 'show',
you can write an instance for IO a that renders all IO harmless. Then
just wrap your user's arbitrary expression in 'show.
This is what lambdabot does. So we have:
Safe, pure expressions, just shown:
20:04 dons> > map (^2) [1..]
20:04 lambdabot> [1,4,9,16,25,36,49,64,81,100,121,144,169,196,225,256,289,324,361,400,441,484...
IO, shown, by a Show instance that renders it harmless:
20:04 dons> > readFile "/etc/passwd"
20:04 lambdabot>
The other possibility is to somehow run GHC under a user context that doesn't *have* write access to anything on the filesystem. That way there is no margin for error.
Well, that's overkill, when you have a pure language, with a strong type system that tags IO. :-)
This leaves only the problem of how to make a web server call GHC. I can think of a number of possibilities. - Write my own HTTP server from scratch. (Not keen...) - Configure Apache to do it. (Is that physically possible?) - Use Apache and some bizzare Perl scripting to do the actual call. (Assuming *that* is possible.) - Use Apache and some Perl scripts to write the data to a text file, and write a small Haskell program to poll the filesystem waiting for request files to appear, run then though GHC, and put the result back into a file. Write another Perl script to slurp up the result and send it back to the caller. - Doesn't Java have a free HTTP server implementation? Maybe I could use that... - ...others?
You could also just use 'runplugs' from lambdabot, which also handles non-terminating programs :-)
(I'm not sure why this should be, but it seems that Don has made several replies to my emails that didn't show up in my inbox, and only show up on the list archives. Oh well, anyway...)
I lurk on the POV-Ray NNTP server, and we recently had quite a discussion about Haskell. I'd *love* to be able to say to people "hey, you don't even need to bother working out how to install GHC, just CLICK THIS LINK and you can play with Haskell instantly!" But at the moment I'm not entirely sure how to set this up. Ideas?
Yeah, an online solution to this would be good. lambdabot gives us a start, lambdaweb goes further. But the last 5% need more work. -- Don

Oh, but there is the *minor* detail that I am literally allowing unauthenticated users to perform arbitrary code execution. For example, .. AFAIK, Lambdabot dissalows any expression that performs IO. In Haskell, this is beautifully easy: reject any expression having an IO type. .. Don't use parsing for security, use the type checker. By using 'show', you can write an instance for IO a that renders all IO harmless. Then just wrap your user's arbitrary expression in 'show.
careful please!-) we've had enough of that kind of issues in scripts, CGI, .. sandboxes, etc. to have learned the lesson that *this is not a minor detail*, and requires full attention to details, especially, but not only if, meta- programming is involved (interpreting input strings as programs, or using hs-plugins, template haskell). two obvious exceptions: 'unsafePerformIO' and FFI. even expressions not involving IO might use it internally (also, you want to disallow both write and read access). less obvious: DOS-style issues, eg, filling the process table or claiming all memory. least obvious: things we've missed. it would really be nice if someone would sit down and sort this all out in detail. there'd still be no guarantee that such a Haskell sandbox was totally safe, but at least all issues and solutions could be shared, making it as safe as the community knows how. claus

claus.reinke:
Oh, but there is the *minor* detail that I am literally allowing unauthenticated users to perform arbitrary code execution. For example, .. AFAIK, Lambdabot dissalows any expression that performs IO. In Haskell, this is beautifully easy: reject any expression having an IO type. .. Don't use parsing for security, use the type checker. By using 'show', you can write an instance for IO a that renders all IO harmless. Then just wrap your user's arbitrary expression in 'show.
careful please!-) we've had enough of that kind of issues in scripts, CGI, .. sandboxes, etc. to have learned the lesson that *this is not a minor detail*, and requires full attention to details, especially, but not only if, meta- programming is involved (interpreting input strings as programs, or using hs-plugins, template haskell).
two obvious exceptions: 'unsafePerformIO' and FFI. even expressions not involving IO might use it internally (also, you want to disallow both write and read access). less obvious: DOS-style issues, eg, filling the process table or claiming all memory. least obvious: things we've missed.
it would really be nice if someone would sit down and sort this all out in detail. there'd still be no guarantee that such a Haskell sandbox was totally safe, but at least all issues and solutions could be shared, making it as safe as the community knows how.
Claus is right. You need type guarantees, and more! Lambdabot uses 1) type guarantee of no-IO at the top level, along with 2) a trusted module base (pure module only, that are trusted to not export evil things), as well as 3) restricting only to H98-language only (things like TH can, and have been, exploited, for example). So, no-IO type, trusted base of no FFI, no unsafe*, resource limits, and no extensions beyond H98, then , hopefully, we're ok. -- Don

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Donald Bruce Stewart wrote:
Lambdabot uses 1) type guarantee of no-IO at the top level, along with 2) a trusted module base (pure module only, that are trusted to not export evil things), as well as 3) restricting only to H98-language only (things like TH can, and have been, exploited, for example).
And lambdabot's only allowing _expressions_, so GHC's (former?) vulnerability to instances of Ix that return out-of-bounds indexes did not affect it. There are some extensions that are safe... explicit forall, rank-N types, etc... which can be enabled on an "opt-in" basis so that only safe ones are chosen? Isaac -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGWE1oHgcxvIWYTTURAls9AKDSwV4zW/GcpZQVGi+9n+EBfWr15ACePP3h r7G5fr7Ac8RezZZ7fXNRjHE= =UWFu -----END PGP SIGNATURE-----

isaacdupree:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Donald Bruce Stewart wrote:
Lambdabot uses 1) type guarantee of no-IO at the top level, along with 2) a trusted module base (pure module only, that are trusted to not export evil things), as well as 3) restricting only to H98-language only (things like TH can, and have been, exploited, for example).
And lambdabot's only allowing _expressions_, so GHC's (former?) vulnerability to instances of Ix that return out-of-bounds indexes did not affect it.
Oh yes, it only allows expressions (how could I forget that?), meaning also that, for example, crafty newtype recursion is disallowed. And of course, no evil Ix instances. Oh, also, there's another exploit using a variety crafty expressions that trigger pathological type inference behaviour, causing the type checker to effectively lock up the system. (One is particularly easy to come up with...). There's really a lot of things to watch out for, actually. We should document all the interesting exploits that have been found over the years!
There are some extensions that are safe... explicit forall, rank-N types, etc... which can be enabled on an "opt-in" basis so that only safe ones are chosen?
We could do that (explicit forall is probably the most requested). Currently we only allow -fextended-defaulting, (giving ghci like defaulting). -- Don

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Donald Bruce Stewart wrote:
isaacdupree:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Donald Bruce Stewart wrote:
Lambdabot uses 1) type guarantee of no-IO at the top level, along with 2) a trusted module base (pure module only, that are trusted to not export evil things), as well as 3) restricting only to H98-language only (things like TH can, and have been, exploited, for example). And lambdabot's only allowing _expressions_, so GHC's (former?) vulnerability to instances of Ix that return out-of-bounds indexes did not affect it.
Oh yes, it only allows expressions (how could I forget that?), meaning also that, for example, crafty newtype recursion is disallowed. And of course, no evil Ix instances.
and no imports of course... not even renamings like "import Data.Map as Map" or so.
Oh, also, there's another exploit using a variety crafty expressions that trigger pathological type inference behaviour, causing the type checker to effectively lock up the system. (One is particularly easy to come up with...). There's really a lot of things to watch out for, actually.
We should document all the interesting exploits that have been found over the years!
Ok, I'm making http://haskell.org/haskellwiki/Safely_running_untrusted_Haskell_code
There are some extensions that are safe... explicit forall, rank-N types, etc... which can be enabled on an "opt-in" basis so that only safe ones are chosen?
We could do that (explicit forall is probably the most requested). Currently we only allow -fextended-defaulting, (giving ghci like defaulting).
At least to the extent that separately enabling extensions is presently supported in GHC.
The security mechanisms were briefly described in the 2004 hs-plugins paper, if I recall, but otherwise, I don't think we've documented the techniques.
You could put a reference (link) to that paper if it's worth it Isaac -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGWF/3HgcxvIWYTTURAkP0AKDSAiJz2kYTe54cipOZOxVZCl+engCfX4Kq Q+3dwkNf5JkjMHqVERHcegA= =9LZ6 -----END PGP SIGNATURE-----

On 5/26/07, Isaac Dupree
We should document all the interesting exploits that have been found over the years!
Ok, I'm making http://haskell.org/haskellwiki/Safely_running_untrusted_Haskell_code
That page mentions:
* very large array allocations can integer overflow the storage
manager, allowing arbitrary memory access
Does this still happen? Sounds like a serious bug in the runtime.
--
Gaal Yahas

On Mon, May 28, 2007 at 07:26:46PM +0300, Gaal Yahas wrote:
On 5/26/07, Isaac Dupree
wrote: We should document all the interesting exploits that have been found over the years!
Ok, I'm making http://haskell.org/haskellwiki/Safely_running_untrusted_Haskell_code
That page mentions:
* very large array allocations can integer overflow the storage manager, allowing arbitrary memory access
Does this still happen? Sounds like a serious bug in the runtime.
stefan@stefans:~$ ghci ___ ___ _ / _ \ /\ /\/ __(_) / /_\// /_/ / / | | GHC Interactive, version 6.7.20070518, for Haskell 98. / /_\\/ __ / /___| | http://www.haskell.org/ghc/ \____/\/ /_/\____/|_| Type :? for help. Loading package base ... linking ... done. Prelude> :m + Array Prelude Array> array (0::Int, maxBound) [(1000000,'x')] array (0,2147483647) [(0,Segmentation fault Stefan

Don't use parsing for security, use the type checker. By using 'show', you can write an instance for IO a that renders all IO harmless. Then just wrap your user's arbitrary expression in 'show.
OK, what... the... hell...? I just looked on the list archive, and sure enough that's a quote from yet another email I didn't receive. I have seriously got to figure out why I'm not seeing these emails...
careful please!-) we've had enough of that kind of issues in scripts, CGI, .. sandboxes, etc. to have learned the lesson that *this is not a minor detail*, and requires full attention to details, especially, but not only if, meta- programming is involved (interpreting input strings as programs, or using hs-plugins, template haskell).
two obvious exceptions: 'unsafePerformIO' and FFI. even expressions not involving IO might use it internally (also, you want to disallow both write and read access). less obvious: DOS-style issues, eg, filling the process table or claiming all memory. least obvious: things we've missed.
it would really be nice if someone would sit down and sort this all out in detail. there'd still be no guarantee that such a Haskell sandbox was totally safe, but at least all issues and solutions could be shared, making it as safe as the community knows how.
...which brings us back to my suggestion for "let's just deny all access to stuff it shouldn't have at the OS level - that way I can't possibly miss any edge cases". (BTW, good luck doing FFI over a text-only interface...) IIRC, there's a CLI switch that you can use to make GHC limit the amount of memory it consumes. (Actually the RTS, but since GHC is compiled with GHC...) I'm not aware of any such switch to limit the amount of time, so I might have to write actual code for that one... And then there's the issue of limiting the number of concurrent expressions being executed to some sane number. By the way... what's "plugs"? I cannot discover any information about this.

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Andrew Coppin wrote:
Don't use parsing for security, use the type checker. By using 'show', you can write an instance for IO a that renders all IO harmless. Then just wrap your user's arbitrary expression in 'show.
OK, what... the... hell...?
I just looked on the list archive, and sure enough that's a quote from yet another email I didn't receive. I have seriously got to figure out why I'm not seeing these emails...
Maybe something's spam-filtering it on the way to you, and I believe the default list settings are to not send copies to e-mail addresses already in a "to" or "cc" field. Sometimes when I do "reply all" on a mailing list, one of the e-mail addresses I'm replying to replies that the message was not deliverable, or was considered spam, or whatever; and I know there also exist spam-filters that aren't nice enough to tell the sender. Isaac -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGWEvqHgcxvIWYTTURAq+oAKDQHuNlbHJXEt6DmFaMCQ9UE+z7lgCfeuus zF54yISzfnscJQn1dtBpS/I= =+fbi -----END PGP SIGNATURE-----

it would really be nice if someone would sit down and sort this all out in detail. there'd still be no guarantee that such a Haskell sandbox was totally safe, but at least all issues and solutions could be shared, making it as safe as the community knows how.
The #haskell people have been working on this for about 3 years now. The result is the 'runplugs' program, which I've talked about in previous mails. http://www.cse.unsw.edu.au/~dons/code/lambdabot/scripts/RunPlugs.hs It uses hs-plugins for the evaluation, along with the points about IO prevention via type checking, resource limits controlled by the OS, language extension preventions, and a trusted (audited) module base. The security mechanisms were briefly described in the 2004 hs-plugins paper, if I recall, but otherwise, I don't think we've documented the techniques. Maybe we should, as many issues have been encountered over the years, further and further constraining the kinds of things that are allowed. -- Don

The #haskell people have been working on this for about 3 years now. The result is the 'runplugs' program, which I've talked about in previous mails.
http://www.cse.unsw.edu.au/~dons/code/lambdabot/scripts/RunPlugs.hs
It uses hs-plugins for the evaluation, along with the points about IO prevention via type checking, resource limits controlled by the OS, language extension preventions, and a trusted (audited) module base.
great! and since it is presumably in daily use, there is both pressure to fix holes as soon as they are discovered, and ongoing discovery in a safe (or at least friendly) environment. still, that only gives us a box. how about some more sand?-) for instance, one could try to provide a safe redefinition of some basic IO operations, such as reading and writing a limited amount of files below a local directory? of course, permitting some IO is trickier than ruling out all IO (standard example: i really meant 'below', as in prefixing all paths and ruling out upward links like '..', not just 'relative to';).
The security mechanisms were briefly described in the 2004 hs-plugins paper, if I recall, but otherwise, I don't think we've documented the techniques. Maybe we should, as many issues have been encountered over the years, further and further constraining the kinds of things that are allowed.
documenting the techniques would ease verification, and make it easier to check what you've already covered and what might yet be missing. for instance, i assume that hs-plugins, unlike ghci, does not permit direct access to qualified names (in ghci, i can refer to 'System.IO.Unsafe.unsafePerformIO' without 'import' or ':m +')? and i assume that even though you only limit time, there is no way to use up all space in no time? you do seem to be protected against this simple one, but it might give others something to think about (no explicit i/o, no imports, no recursion, only expressions): let {p x y f = f x y; f x = p x x} in f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f f)))))))))))))))))) f claus

claus.reinke:
The #haskell people have been working on this for about 3 years now. The result is the 'runplugs' program, which I've talked about in previous mails.
http://www.cse.unsw.edu.au/~dons/code/lambdabot/scripts/RunPlugs.hs
It uses hs-plugins for the evaluation, along with the points about IO prevention via type checking, resource limits controlled by the OS, language extension preventions, and a trusted (audited) module base.
great! and since it is presumably in daily use, there is both pressure to fix holes as soon as they are discovered, and ongoing discovery in a safe (or at least friendly) environment.
still, that only gives us a box. how about some more sand?-) for instance, one could try to provide a safe redefinition of some basic IO operations, such as reading and writing a limited amount of files below a local directory? of course, permitting some IO is trickier than ruling out all IO (standard example: i really meant 'below', as in prefixing all paths and ruling out upward links like '..', not just 'relative to';).
The security mechanisms were briefly described in the 2004 hs-plugins paper, if I recall, but otherwise, I don't think we've documented the techniques. Maybe we should, as many issues have been encountered over the years, further and further constraining the kinds of things that are allowed.
documenting the techniques would ease verification, and make it easier to check what you've already covered and what might yet be missing. for instance, i assume that hs-plugins, unlike ghci, does not permit direct access to qualified names (in ghci, i can refer to
Precisely.
'System.IO.Unsafe.unsafePerformIO' without 'import' or ':m +')? and i assume that even though you only limit time, there is no way to use up all space in no time?
ulimits, from the shell, yes. Though ...
you do seem to be protected against this simple one, but it might give others something to think about (no explicit i/o, no imports, no recursion, only expressions):
let {p x y f = f x y; f x = p x x} in f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f f)))))))))))))))))) f
Exactly. This will trigger a timeout, when ghc fails to typecheck it in 3 seconds. -- Don

claus.reinke:
The #haskell people have been working on this for about 3 years now. The result is the 'runplugs' program, which I've talked about in previous mails.
http://www.cse.unsw.edu.au/~dons/code/lambdabot/scripts/RunPlugs.hs
It uses hs-plugins for the evaluation, along with the points about IO prevention via type checking, resource limits controlled by the OS, language extension preventions, and a trusted (audited) module base.
great! and since it is presumably in daily use, there is both pressure to fix holes as soon as they are discovered, and ongoing discovery in a safe (or at least friendly) environment.
I've listed the mechanisms we use, and exploits that have been thought of, or discovered, over the years, on the page: http://haskell.org/haskellwiki/Safely_running_untrusted_Haskell_code -- Don

Donald Bruce Stewart wrote:
claus.reinke:
The #haskell people have been working on this for about 3 years now. The result is the 'runplugs' program, which I've talked about in previous mails.
http://www.cse.unsw.edu.au/~dons/code/lambdabot/scripts/RunPlugs.hs
It uses hs-plugins for the evaluation, along with the points about IO prevention via type checking, resource limits controlled by the OS, language extension preventions, and a trusted (audited) module base.
great! and since it is presumably in daily use, there is both pressure to fix holes as soon as they are discovered, and ongoing discovery in a safe (or at least friendly) environment.
I've listed the mechanisms we use, and exploits that have been thought of, or discovered, over the years, on the page:
http://haskell.org/haskellwiki/Safely_running_untrusted_Haskell_code
I'm liking where this is going... ;-) Personally, I would think that denying access to "dangerous" funtions - or better yet, only allowing access to obviously "safe" functions - would be one half the problem, and using OS constraints to enforce resource limits would be the other half. But then, I'm no expert, so perhaps I've missed something...

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Donald Bruce Stewart wrote:
I've listed the mechanisms we use, and exploits that have been thought of, or discovered, over the years, on the page:
http://haskell.org/haskellwiki/Safely_running_untrusted_Haskell_code
The exception handling behavior is somewhat odd, I don't even understand it fully. Here's a lambdabot session... why is the behavior of the "iter" versions different from the explicitly iterated "error"? isaacd > error "hi" lambdabot Exception: hi isaacd > error (error "hi") lambdabot Exception: hi isaacd > error ('l':(error "hi")) lambdabot Exception isaacd > fix error lambdabot Exception: <<loop>> isaacd > fix (error . ('a':)) lambdabot Exception isaacd > fix (error . (replicate 5000 'a'++)) [ long lines clipped by me: ] lambdabot Exception: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa[...] lambdabot aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa[...] lambdabot aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa[...] lambdabot aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa[...] lambdabot aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa isaacd > error (error (error "hi")) :: String lambdabot Exception: hi isaacd > error.error.error . error.error.error . error.error.error . error.error.error . error.error.error . error.error.error . error.error.error . error.error.error . error.error.error . error.error.error . error.error.error . error.error.error . error.error.error . error.error.error . error.error.error . error.error.error . error.error.error . error.error.error . error.error.error $ "hi" lambdabot Exception: hi isaacd > let iter 0 _ = id; iter n f = f . iter (n - 1) f in iter 0 error "hi" lambdabot "hi" isaacd > let iter 0 _ = id; iter n f = f . iter (n - 1) f in iter 1 error "hi" lambdabot Exception: hi isaacd > let iter 0 _ = id; iter n f = f . iter (n - 1) f in iter 2 error "hi" lambdabot Exception isaacd > let iter 0 _ = id; iter n f = f . iter (n - 1) f in iter 1001 error "hi" lambdabot Exception isaacd > let iter 0 _ = id; iter n f = f . iter (n - 1) f in iter 5 ('L':) "hi" lambdabot "LLLLLhi" Isaac -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGWWo/HgcxvIWYTTURAhYdAJsExQDI9191Q1y9u66H+gpWVlJv2ACfVEhZ IQWCLIgqWksbEcZ+g7gsjR0= =d4Lk -----END PGP SIGNATURE-----

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Donald Bruce Stewart wrote:
I've listed the mechanisms we use, and exploits that have been thought of, or discovered, over the years, on the page:
http://haskell.org/haskellwiki/Safely_running_untrusted_Haskell_code
Lambdabot uses is the technique of using a space at the beginning of the line to make sure it doesn't do anything special. However, it seems currently for multiple lines (long string or error string) it only puts a space if the first character is '@' ('?', '>', '/', '\001', '\000' are all sent literally). This behavior seems odd (why do it for '@'? and why not always a space?). In XChat the '\000' prevented the rest of the message from appearing, in the unescaped version produced by 'error'. Try (with any string in place of "?botsnack") @run (\str -> replicate 198 'a' ++ str ++ replicate (199 - length str) ' ') "?botsnack" or @run (\str -> error (replicate 188 'a' ++ str)) "?botsnack" (at least lambdabot doesn't respond to itself:) Isaac -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGWXCmHgcxvIWYTTURAkrlAKCcxS/kjtqtJCwZl3SrV7q7QyOL0QCgpeKS 9crkBNfI4QYzCn9P+2f7gCk= =8Tsr -----END PGP SIGNATURE-----

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Donald Bruce Stewart wrote:
I've listed the mechanisms we use, and exploits that have been thought of, or discovered, over the years, on the page:
http://haskell.org/haskellwiki/Safely_running_untrusted_Haskell_code
(Maybe some of the discussion should move to the talk page?) which is making me think. "The expression is bound to a random top level identifier (harmless to guess)" What about the non-recursive case ...expr... of x -> take 2048 (show x) this way expr can't refer to x (it doesn't at all need to be randomly generated this way) and definitely can't bind other things like take and show (they probably should be qualified anyway) Isaac -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGWbWYHgcxvIWYTTURAmI8AJ9cesD8W26GWjENhwVUpxU997c+SwCeO1F9 iPqHvwztBJH78S4PT4/TpNI= =0xzE -----END PGP SIGNATURE-----

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Isaac Dupree wrote:
"The expression is bound to a random top level identifier (harmless to guess)"
What about the non-recursive
case ...expr... of x -> take 2048 (show x)
this way expr can't refer to x (it doesn't at all need to be randomly generated this way) and definitely can't bind other things like take and show (they probably should be qualified anyway)
er, wait, I'm confused. Is it top-level? If not, it could just be take 2048 (show ( ...expr... )) and it doesn't look top-level to me from the lambdabot code in scripts/RunPlugs.hs Isaac -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGWbi8HgcxvIWYTTURAqaMAKCxzKOW+6RDe2kTG6KX8lktQnwY1QCgyO5S jCJQKnGhAi3NLO1bzzbeLzI= =Innv -----END PGP SIGNATURE-----

isaacdupree:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Isaac Dupree wrote:
"The expression is bound to a random top level identifier (harmless to guess)"
What about the non-recursive
case ...expr... of x -> take 2048 (show x)
this way expr can't refer to x (it doesn't at all need to be randomly generated this way) and definitely can't bind other things like take and show (they probably should be qualified anyway)
er, wait, I'm confused. Is it top-level? If not, it could just be
take 2048 (show ( ...expr... ))
and it doesn't look top-level to me from the lambdabot code in scripts/RunPlugs.hs
Ah right. No, it is bound to a top level value, but is itself not -- its a local binding so we can use {-# #-} pragmas to get more precise error messages (if I recall correctly). -- Don

Donald Bruce Stewart wrote:
The #haskell people have been working on this for about 3 years now. The result is the 'runplugs' program, which I've talked about in previous mails.
http://www.cse.unsw.edu.au/~dons/code/lambdabot/scripts/RunPlugs.hs
It uses hs-plugins for the evaluation, along with the points about IO prevention via type checking, resource limits controlled by the OS, language extension preventions, and a trusted (audited) module base.
The security mechanisms were briefly described in the 2004 hs-plugins paper, if I recall, but otherwise, I don't think we've documented the techniques. Maybe we should, as many issues have been encountered over the years, further and further constraining the kinds of things that are allowed.
For me, the unfortunate thing is that there seems to be no interpreter for Haskell written in Haskell. (Except for GHC, which is *huge*.) We have a Haskell parser [which is complex beyond usability], but no interpreter. It would be nice if one existed, and I'm trying to implement one... but on the other hand, one doesn't want to say to people "hey, come learn Haskell, try this web interpreter" and then have them find it doesn't implement Haskell precisely. So it looks like I'm stuck with present technology - and that essentially means GHC. (Other compilers? What other compilers??) As far as I know, hs-plugins works by taking an expression, writing it to a file, calling GHC to parse it, transform it to Core, optimise it, transform it to STG, optimise it, transform it to C--, optimise it, transform it to ANSI C, optimise it, pass it to GCC, compile it, link it, and *then* using the GHC runtime linker to load the generated object code into memory, type-check it, and, finally, execute it. OTOH, GHCi just takes an expression, parses it and interprets it. This appears to be a *much* more lightweight approach. I have had some success in using the GHC API to write a program that is essentially GHCi - you type stuff in, it executes it. Now, if I could write a complete full-featured HTTP server and feed that into it instead of stdin and stdout, I could make a web server for executing Haskell... But, hmm, that's not going to happen any time soon. ...or, I could use GHC -e as I described earlier. But I have to look at figuring out how to prevent it doing Bad Things. (Lambdabot gives me an idea. Write a module that imports all the stuff you might want interactively, and process the user-supplied script to make sure it doesn't issue any imports, and then you can precisely control what functions the code can call.) Whatever... I'd just like to see an online way to run Haskell, and since the Lambdabot webpage still shows no sign of working...

HI
For me, the unfortunate thing is that there seems to be no interpreter for Haskell written in Haskell. (Except for GHC, which is *huge*.)
What do you mean by *huge*? Takes up to much memory at runtime? Requires too long to compile? Has had too many experts spending lots of time writing it? A large volume of source code isn't a negative, unless you are expected to do something with it that involves modifying a large chunk of it.
We have a Haskell parser [which is complex beyond usability]
Which takes a Haskell file and produces an abstract syntax tree representing Haskell? I'm not sure how that's complex, it does exactly what it says on the tin - it parses Haskell.
them find it doesn't implement Haskell precisely. So it looks like I'm stuck with present technology - and that essentially means GHC. (Other compilers? What other compilers??)
Yhc, Hugs, JHC...
As far as I know, hs-plugins works by taking an expression, writing it to a file, calling GHC to parse it, transform it to Core, optimise it, transform it to STG, optimise it, transform it to C--, optimise it, transform it to ANSI C, optimise it, pass it to GCC, compile it, link it, and *then* using the GHC runtime linker to load the generated object code into memory, type-check it, and, finally, execute it.
Are you complaining that this process is too slow? Complaints about speed should take the form "I expected this to happen in 3 seconds, it requires 12". You can't have a complaint about it doing clever things automatically for you, only that the results of those clever things don't meet your needs.
Whatever... I'd just like to see an online way to run Haskell, and since the Lambdabot webpage still shows no sign of working...
Writing a Haskell interpreter seems like a lot of work, if all you want is "a few tweaks to lambdabot". Of course, a Haskell interpreter is something I'd love to see :) Thanks Neil

Neil Mitchell wrote:
HI
For me, the unfortunate thing is that there seems to be no interpreter for Haskell written in Haskell. (Except for GHC, which is *huge*.)
What do you mean by *huge*? Takes up to much memory at runtime? Requires too long to compile? Has had too many experts spending lots of time writing it? A large volume of source code isn't a negative, unless you are expected to do something with it that involves modifying a large chunk of it.
It's too large and complicated to use for small things. E.g., if you want to just dash off a little something that needs to evaluate an expression... Well, you can use the GHC API. But this is highly nontrivial. You get the impression it was added later, and the internal structure of GHC is so complex that it makes it hard to write a lightweight interface to it.
We have a Haskell parser [which is complex beyond usability]
Which takes a Haskell file and produces an abstract syntax tree representing Haskell? I'm not sure how that's complex, it does exactly what it says on the tin - it parses Haskell.
First, there is the minor point that you can't parse a Haskell expression - only an entire Haskell module. Then we come to the real problem: Sure, it parses Haskell. Into a *giant* data structure that could take many decades to map out. And that's because it keeps every minute detail of the original source. For example, the expressions "1 + 1" and "(+) 1 1" parse differently and give different trees, despite representing the exact same language construct. I want an *abstract* tree, that just represents the semantics of the expression, not every minute syntactic detail. (Although the latter might be useful in other contexts - syntax hilighting perhaps.)
them find it doesn't implement Haskell precisely. So it looks like I'm stuck with present technology - and that essentially means GHC. (Other compilers? What other compilers??)
Yhc, Hugs, JHC...
I don't know about Linux, but Hugs is currently hopelessly unstable on Windoze. As for the others... I've not used them, but the Haskell Wiki makes it sound like they're all immature research projects rather than end-user usable compilers. (I don't know how true that is.)
As far as I know, hs-plugins works by taking an expression, writing it to a file, calling GHC to parse it, transform it to Core, optimise it, transform it to STG, optimise it, transform it to C--, optimise it, transform it to ANSI C, optimise it, pass it to GCC, compile it, link it, and *then* using the GHC runtime linker to load the generated object code into memory, type-check it, and, finally, execute it.
Are you complaining that this process is too slow? Complaints about speed should take the form "I expected this to happen in 3 seconds, it requires 12". You can't have a complaint about it doing clever things automatically for you, only that the results of those clever things don't meet your needs.
It just seems vastly overkill to generate native executable code for something you only want to execute once, which is probably only going to take a fraction of a second anyway.
Whatever... I'd just like to see an online way to run Haskell, and since the Lambdabot webpage still shows no sign of working...
Writing a Haskell interpreter seems like a lot of work, if all you want is "a few tweaks to lambdabot". Of course, a Haskell interpreter is something I'd love to see :)
Well, we'll see. I keep telling people I'm going to write a Haskell to Java compiler, and yet no code ever seems to get written... *sigh*

On Sat, May 26, 2007 at 08:12:13PM +0100, Andrew Coppin wrote:
It's too large and complicated to use for small things. E.g., if you want to just dash off a little something that needs to evaluate an expression... Well, you can use the GHC API. But this is highly nontrivial. You get the impression it was added later,
That's because it /was/ added later! Concrete suggestions of changes to the API which would make it easier to use are definitely welcomed; the GHC bug tracker is probably the best place to put them. We'd much prefer to change the API to become easier to use than for everyone to have to work around its idiosyncrasies.
I don't know about Linux, but Hugs is currently hopelessly unstable on Windoze.
Have you filed bugs in the hugs bug tracker? Thanks Ian

Hi
I don't know about Linux, but Hugs is currently hopelessly unstable on Windoze.
Have you filed bugs in the hugs bug tracker?
No bugs have been filed from this. In general Windows and Hugs is rock solid, I use it every single day without issue - including to develop Yhc (an compiler). If Andrew is having any problems, please share them (hugs-bugs -at- haskell.org). Thanks Neil

Neil Mitchell wrote:
Hi
I don't know about Linux, but Hugs is currently hopelessly unstable on Windoze.
Have you filed bugs in the hugs bug tracker?
No bugs have been filed from this. In general Windows and Hugs is rock solid, I use it every single day without issue - including to develop Yhc (an compiler). If Andrew is having any problems, please share them (hugs-bugs -at- haskell.org).
IIRC, I did have a look at the bugtracker once, and several people seemed to have reported bugs similar to the ones I'm seeing. It's a shame really; the 2003 release of Hugs worked flawlessly. The new 2006 release has a much nicer UI, but... it behaves unpredictably. In particular, it has a habit of printing garbage instead of computation results. (Sometimes the correct result is truncated, sometimes parts of previous outputs - or the welcome banner - is reprinted instead of the output. Sometimes the output it printed multiple times. Sometimes valid Haskell generates spurious parse or type errors, but if you restart Hugs it works fine, etc.) Also, more than once I've been visited by Dr Watson. I don't care *what* you do to a program, it should _never_ crash that badly... There is also the minor detail that the uninstaller doesn't actually work. ("The NTVDM CPU has encountered an illegal instruction...") So I can't even remove the program from my computer now. :-(

Hi
It's a shame really; the 2003 release of Hugs worked flawlessly. The new 2006 release has a much nicer UI, but... it behaves unpredictably. In particular, it has a habit of printing garbage instead of computation results.
This is not in the bug tracker. Do you have a reproducible test case? I think I fixed one bug related to this a while back.
Also, more than once I've been visited by Dr Watson. I don't care *what* you do to a program, it should _never_ crash that badly...
I've never crashed WinHugs, ever. If you could say *what* crashes Hugs we'd have a much better chance and fixing it.
There is also the minor detail that the uninstaller doesn't actually work. ("The NTVDM CPU has encountered an illegal instruction...") So I can't even remove the program from my computer now. :-(
Just delete the directory and you'll be fine, it doesn't install .dll's in Windows directories etc. This is a known bug, and on the bug tracker, and will be fixed in a new release shortly. Thanks Neil

Neil Mitchell wrote:
Hi
It's a shame really; the 2003 release of Hugs worked flawlessly. The new 2006 release has a much nicer UI, but... it behaves unpredictably. In particular, it has a habit of printing garbage instead of computation results.
This is not in the bug tracker. Do you have a reproducible test case? I think I fixed one bug related to this a while back.
Unfortunately it seems very intermittent. Sometimes it works fine, sometimes it just acts weirdly at me. It is of course possible that the "one bug" you fixed is the one I'm seeing...
Also, more than once I've been visited by Dr Watson. I don't care *what* you do to a program, it should _never_ crash that badly...
I've never crashed WinHugs, ever. If you could say *what* crashes Hugs we'd have a much better chance and fixing it.
Again, intermittent, can't reliably reproduce. This one is a lot rarer than the first, fortunately.
There is also the minor detail that the uninstaller doesn't actually work. ("The NTVDM CPU has encountered an illegal instruction...") So I can't even remove the program from my computer now. :-(
Just delete the directory and you'll be fine, it doesn't install .dll's in Windows directories etc. This is a known bug, and on the bug tracker, and will be fixed in a new release shortly.
OK. Thanks for that.

Hi
This is not in the bug tracker. Do you have a reproducible test case? I think I fixed one bug related to this a while back.
Unfortunately it seems very intermittent. Sometimes it works fine, sometimes it just acts weirdly at me.
It was a multithreaded/locking bug, the worst kind to track down and rarely repeatable. I think I quashed it though, but if you see it again in the next release please let me know.
Also, more than once I've been visited by Dr Watson. I don't care *what* you do to a program, it should _never_ crash that badly...
I've never crashed WinHugs, ever. If you could say *what* crashes Hugs we'd have a much better chance and fixing it.
Again, intermittent, can't reliably reproduce. This one is a lot rarer than the first, fortunately.
Anything to do with the FFI? At load time or run time? If it reoccurs please jot down any details you have. Thanks Neil

Neil Mitchell wrote:
Hi
This is not in the bug tracker. Do you have a reproducible test case? I think I fixed one bug related to this a while back.
Unfortunately it seems very intermittent. Sometimes it works fine, sometimes it just acts weirdly at me.
It was a multithreaded/locking bug, the worst kind to track down and rarely repeatable. I think I quashed it though, but if you see it again in the next release please let me know.
Ah, God bless nondeterministic software! ;-)
Also, more than once I've been visited by Dr Watson. I don't care *what* you do to a program, it should _never_ crash that badly...
I've never crashed WinHugs, ever. If you could say *what* crashes Hugs we'd have a much better chance and fixing it.
Again, intermittent, can't reliably reproduce. This one is a lot rarer than the first, fortunately.
Anything to do with the FFI? At load time or run time? If it reoccurs please jot down any details you have.
...Hugs can do FFI?? o_O

| It's too large and complicated to use for small things. E.g., if you | want to just dash off a little something that needs to evaluate an | expression... Well, you can use the GHC API. But this is highly | nontrivial. You get the impression it was added later, and the internal | structure of GHC is so complex that it makes it hard to write a | lightweight interface to it. It's certainly true that GHC's API was added later. But there is no real reason why it should not be easy to use. We'd be keen to support anyone who wanted to help make that happen. At the moment there's a bit of chicken and egg problem. Simon

Simon Peyton-Jones wrote:
| It's too large and complicated to use for small things. E.g., if you | want to just dash off a little something that needs to evaluate an | expression... Well, you can use the GHC API. But this is highly | nontrivial. You get the impression it was added later, and the internal | structure of GHC is so complex that it makes it hard to write a | lightweight interface to it.
It's certainly true that GHC's API was added later. But there is no real reason why it should not be easy to use. We'd be keen to support anyone who wanted to help make that happen. At the moment there's a bit of chicken and egg problem.
Perhaps I was unduly harsh here. Let me phrase it thus: It seems to me that GHC represents a *huge* amount of development work. (I don't know how long you guys have been working on this thing...) On one hand, when you want to do something with the Haskell language, the idea of loafing off and letting GHC do all the donkey work for you is very appealing. On the other hand, the design goals of GHC seem to be to produce top-quality compiled code, and to be as user-friendly as possible. (These are not goals I'm going to argue with!) It seems making the internal workings of GHC as simple as possible is not a big goal (although I don't suppose you go out of your way to make it *hard*). GHC is designed to be good at being GHC, rather than good at being a collection of flexible, reusable Haskell processing libraries. In my case, all I was actually trying to do was implement GHCi. (It's a good first test.) It took me a few hours, but I did in fact eventually get it to work. My plan was to make a program that's essentially GHCi, but accepts commands remotely via TCP. But by that point I'd decided that maybe just invoking GHC.EXE manually might be significantly easier. It's certainly nowhere near as easy as JavaScript's eval() function. (But then, Haskell isn't JavaScript, so maybe it's not reasonable to expect this level of ease. I don't know.) Mainly what took the time is that thus stuff doesn't appear to be very well documented. (Presumably most GHC developers are busy... developing... GHC...) I did eventually get my test program to work, and the code wasn't especially large or complex. (Although it was entirely devoid of error handling.) I'm a little curios as to why the binary was several times larger than either GHC or GHCi, but still. I didn't see any way to access facilities other than compilation/evaluation. (E.g., what type does this have, or please desugar this.) But then, I didn't look very hard. Still, it's not like I could have done any better myself, so maybe I should just quit whining...

On May 28, 2007, at 5:49 , Andrew Coppin wrote:
not a big goal (although I don't suppose you go out of your way to make it *hard*). GHC is designed to be good at being GHC, rather than good at being a collection of flexible, reusable Haskell processing libraries.
Enh. That's no reason not to *try* to be.
I didn't see any way to access facilities other than compilation/ evaluation. (E.g., what type does this have, or please desugar this.) But then, I didn't look very hard.
You might want to look at Shim (http://shim.haskellco.de/trac/) --- it uses GHC-API to do things like asking for the type of arbitrary variables or expressions. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

Brandon S. Allbery KF8NH wrote:
On May 28, 2007, at 5:49 , Andrew Coppin wrote:
not a big goal (although I don't suppose you go out of your way to make it *hard*). GHC is designed to be good at being GHC, rather than good at being a collection of flexible, reusable Haskell processing libraries.
Enh. That's no reason not to *try* to be.
I agree. I'm just pointing out that these are somewhat comflicting goals, and currently (it seems to me) GHC is more focused on being GHC. (Which is not something I'm going to complain about too loudly. ;-)
I didn't see any way to access facilities other than compilation/evaluation. (E.g., what type does this have, or please desugar this.) But then, I didn't look very hard.
You might want to look at Shim (http://shim.haskellco.de/trac/) --- it uses GHC-API to do things like asking for the type of arbitrary variables or expressions.
I'll take a look...

On Mon, 2007-05-28 at 10:49 +0100, Andrew Coppin wrote:
Simon Peyton-Jones wrote:
| It's too large and complicated to use for small things. E.g., if you | want to just dash off a little something that needs to evaluate an | expression... Well, you can use the GHC API. But this is highly | nontrivial. You get the impression it was added later, and the internal | structure of GHC is so complex that it makes it hard to write a | lightweight interface to it.
It's certainly true that GHC's API was added later. But there is no real reason why it should not be easy to use. We'd be keen to support anyone who wanted to help make that happen. At the moment there's a bit of chicken and egg problem.
In my case, all I was actually trying to do was implement GHCi. (It's a good first test.) It took me a few hours, but I did in fact eventually get it to work. My plan was to make a program that's essentially GHCi, but accepts commands remotely via TCP.
You looked at the source to GHCi itself I presume? It uses the GHC API, so it's a good place to start with building a variant of GHCi that uses the GHC API :-) Duncan

Duncan Coutts wrote:
In my case, all I was actually trying to do was implement GHCi. (It's a good first test.) It took me a few hours, but I did in fact eventually get it to work. My plan was to make a program that's essentially GHCi, but accepts commands remotely via TCP.
You looked at the source to GHCi itself I presume? It uses the GHC API, so it's a good place to start with building a variant of GHCi that uses the GHC API :-)
No. Actually, as per the wiki, I was looking at the source code to the GHC API. (Apparently there isn't even any Haddock docs, despite the requisit comments existing in the source...) I suppose I could have looked at the source for GHCi - but again I would imagine it's littered with error checking and other user-friendliness, rather than being written to be clearly readable by beginner hackers. ;-) (Also... presumably I'd have to download some giant tarball and work out how to open it. And then find the source code for GHCi amoungst everything else.)

On Mon, 2007-05-28 at 20:14 +0100, Andrew Coppin wrote:
You looked at the source to GHCi itself I presume? It uses the GHC API, so it's a good place to start with building a variant of GHCi that uses the GHC API :-)
No. Actually, as per the wiki, I was looking at the source code to the GHC API. (Apparently there isn't even any Haddock docs, despite the requisit comments existing in the source...)
Yes, it'd be nice to have haddock docs for it.
I suppose I could have looked at the source for GHCi - but again I would imagine it's littered with error checking and other user-friendliness, rather than being written to be clearly readable by beginner hackers. ;-)
I suppose that's probably right. A minimal read-eval loop as a way of seeing how to use the ghc api would be nice.
(Also... presumably I'd have to download some giant tarball and work out how to open it. And then find the source code for GHCi amoungst everything else.)
It's not that scary :-) http://darcs.haskell.org/ghc/compiler/ghci/ Duncan

Duncan Coutts wrote:
On Mon, 2007-05-28 at 20:14 +0100, Andrew Coppin wrote:
You looked at the source to GHCi itself I presume? It uses the GHC API, so it's a good place to start with building a variant of GHCi that uses the GHC API :-)
No. Actually, as per the wiki, I was looking at the source code to the GHC API. (Apparently there isn't even any Haddock docs, despite the requisit comments existing in the source...)
Yes, it'd be nice to have haddock docs for it.
I suppose I could have looked at the source for GHCi - but again I would imagine it's littered with error checking and other user-friendliness, rather than being written to be clearly readable by beginner hackers. ;-)
I suppose that's probably right. A minimal read-eval loop as a way of seeing how to use the ghc api would be nice.
(Also... presumably I'd have to download some giant tarball and work out how to open it. And then find the source code for GHCi amoungst everything else.)
It's not that scary :-)
BTW, you want to look at InteractiveUI.hs and GhciMonad.hs. The rest of the files in that directory belong to the implementation of the bytecode compiler, and hence are *below* the GHC API. One day we'll reorganise the sources to make this clearer. Cheers, Simon

As far as I know, hs-plugins works by taking an expression, writing it to a file, calling GHC to parse it, transform it to Core, optimise it, transform it to STG, optimise it, transform it to C--, optimise it, transform it to ANSI C, optimise it, pass it to GCC, compile it, link it, and *then* using the GHC runtime linker to load the generated object code into memory, type-check it, and, finally, execute it.
Don't forget the Evil Mangler, which optimises the compiled assembly!
http://www.cse.unsw.edu.au/~chak/haskell/ghc/comm/the-beast/mangler.html
On 26/05/07, Andrew Coppin
Donald Bruce Stewart wrote:
The #haskell people have been working on this for about 3 years now. The result is the 'runplugs' program, which I've talked about in previous mails.
http://www.cse.unsw.edu.au/~dons/code/lambdabot/scripts/RunPlugs.hs
It uses hs-plugins for the evaluation, along with the points about IO prevention via type checking, resource limits controlled by the OS, language extension preventions, and a trusted (audited) module base.
The security mechanisms were briefly described in the 2004 hs-plugins paper, if I recall, but otherwise, I don't think we've documented the techniques. Maybe we should, as many issues have been encountered over the years, further and further constraining the kinds of things that are allowed.
For me, the unfortunate thing is that there seems to be no interpreter for Haskell written in Haskell. (Except for GHC, which is *huge*.) We have a Haskell parser [which is complex beyond usability], but no interpreter. It would be nice if one existed, and I'm trying to implement one... but on the other hand, one doesn't want to say to people "hey, come learn Haskell, try this web interpreter" and then have them find it doesn't implement Haskell precisely. So it looks like I'm stuck with present technology - and that essentially means GHC. (Other compilers? What other compilers??)
As far as I know, hs-plugins works by taking an expression, writing it to a file, calling GHC to parse it, transform it to Core, optimise it, transform it to STG, optimise it, transform it to C--, optimise it, transform it to ANSI C, optimise it, pass it to GCC, compile it, link it, and *then* using the GHC runtime linker to load the generated object code into memory, type-check it, and, finally, execute it.
OTOH, GHCi just takes an expression, parses it and interprets it. This appears to be a *much* more lightweight approach. I have had some success in using the GHC API to write a program that is essentially GHCi - you type stuff in, it executes it. Now, if I could write a complete full-featured HTTP server and feed that into it instead of stdin and stdout, I could make a web server for executing Haskell... But, hmm, that's not going to happen any time soon.
...or, I could use GHC -e as I described earlier. But I have to look at figuring out how to prevent it doing Bad Things. (Lambdabot gives me an idea. Write a module that imports all the stuff you might want interactively, and process the user-supplied script to make sure it doesn't issue any imports, and then you can precisely control what functions the code can call.)
Whatever... I'd just like to see an online way to run Haskell, and since the Lambdabot webpage still shows no sign of working...
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Rodrigo Queiro wrote:
As far as I know, hs-plugins works by taking an expression, writing it to a file, calling GHC to parse it, transform it to Core, optimise it, transform it to STG, optimise it, transform it to C--, optimise it, transform it to ANSI C, optimise it, pass it to GCC, compile it, link it, and *then* using the GHC runtime linker to load the generated object code into memory, type-check it, and, finally, execute it.
Don't forget the Evil Mangler, which optimises the compiled assembly!
OMG, how could I forget the Evil Mangler!! :-0 It has such an awesom name! ;-) If I ever get to write a production system, I am *totally* going to have an Evil Mangler module in there somewhere! :-D

overdrigzed:
As far as I know, hs-plugins works by taking an expression, writing it to a file, calling GHC to parse it, transform it to Core, optimise it, transform it to STG, optimise it, transform it to C--, optimise it, transform it to ANSI C, optimise it, pass it to GCC, compile it, link it, and *then* using the GHC runtime linker to load the generated object code into memory, type-check it, and, finally, execute it.
Don't forget the Evil Mangler, which optimises the compiled assembly! [1]http://www.cse.unsw.edu.au/~chak/haskell/ghc/comm/the-bea st/mangler.html
Close, but hs-plugins uses -fasm, so its: File -> Core -> STG -> C-- -> ASM -> ld -> link -> typecheck -> run. Avoiding mangler and gcc. -- Don

On Sat, May 26, 2007 at 07:41:19PM +0100, Andrew Coppin wrote:
Donald Bruce Stewart wrote:
The #haskell people have been working on this for about 3 years now. The result is the 'runplugs' program, which I've talked about in previous mails.
http://www.cse.unsw.edu.au/~dons/code/lambdabot/scripts/RunPlugs.hs
It uses hs-plugins for the evaluation, along with the points about IO prevention via type checking, resource limits controlled by the OS, language extension preventions, and a trusted (audited) module base.
The security mechanisms were briefly described in the 2004 hs-plugins paper, if I recall, but otherwise, I don't think we've documented the techniques. Maybe we should, as many issues have been encountered over the years, further and further constraining the kinds of things that are allowed.
For me, the unfortunate thing is that there seems to be no interpreter for Haskell written in Haskell. (Except for GHC, which is *huge*.) We
Actually, there exists no interpreter for Haskell. Period.
have a Haskell parser [which is complex beyond usability], but no interpreter. It would be nice if one existed, and I'm trying to implement one... but on the other hand, one doesn't want to say to people "hey, come learn Haskell, try this web interpreter" and then have them find it doesn't implement Haskell precisely. So it looks like I'm
Haskell has never been implemented. Every implementation has a large collection of corner cases that aren't correctly parsed; these can be recognized as the wontfix bugs.
stuck with present technology - and that essentially means GHC. (Other compilers? What other compilers??)
As far as I know, hs-plugins works by taking an expression, writing it to a file, calling GHC to parse it, transform it to Core, optimise it, transform it to STG, optimise it, transform it to C--, optimise it, transform it to ANSI C, optimise it, pass it to GCC, compile it, link it, and *then* using the GHC runtime linker to load the generated object code into memory, type-check it, and, finally, execute it.
No, the link step is omitted - the runtime loader works directly on .o files. This cuts several seconds off the sequence, making it neglible compared to IRC lag.
OTOH, GHCi just takes an expression, parses it and interprets it. This
Haha, no. GHCi takes an expression, parses it, wraps it in module Main { main = print (expr) }, type checks it, transforms it to Core, optimizes, transforms to STG, optimizes, transforms to object code for a bytecode machine, links it, and emulates the result. Three times, since it needs to try each of expr, expr >>= print, and print expr. Hugs is also a full compiler, but for some dumb reason doesn't support saving the object code to disk, so you have to recompile everything each time.
appears to be a *much* more lightweight approach. I have had some
Not at all. GHCi seems much faster because GHC's nontrivial startup overhead is amortized over the entire run.
success in using the GHC API to write a program that is essentially GHCi - you type stuff in, it executes it. Now, if I could write a complete full-featured HTTP server and feed that into it instead of stdin and stdout, I could make a web server for executing Haskell... But, hmm, that's not going to happen any time soon.
...or, I could use GHC -e as I described earlier. But I have to look at figuring out how to prevent it doing Bad Things. (Lambdabot gives me an idea. Write a module that imports all the stuff you might want interactively, and process the user-supplied script to make sure it doesn't issue any imports, and then you can precisely control what functions the code can call.)
Whatever... I'd just like to see an online way to run Haskell, and since the Lambdabot webpage still shows no sign of working...
That's my fault - I designed a much simpler configuration interface for lambdabot, but nobody has been motivated to un-bitrot GOA yet. Stefan

Stefan O'Rear wrote:
Actually, there exists no interpreter for Haskell. Period.
Haskell has never been implemented. Every implementation has a large collection of corner cases that aren't correctly parsed; these can be recognized as the wontfix bugs.
Erm... I'm having a "there is no spoon" moment here... Feeling quite lost now...
OTOH, GHCi just takes an expression, parses it and interprets it. This
Haha, no.
GHCi takes an expression, parses it, wraps it in module Main { main = print (expr) }, type checks it, transforms it to Core, optimizes, transforms to STG, optimizes, transforms to object code for a bytecode machine, links it, and emulates the result. Three times, since it needs to try each of expr, expr >>= print, and print expr.
Hugs is also a full compiler, but for some dumb reason doesn't support saving the object code to disk, so you have to recompile everything each time.
I once write a trivial little Tcl script that could parse and execute a biggish subset of Haskell. Given that there are minds out there awesom enough to write an efficient Haskell compiler, you'd think a naive little interpreter for running small expressions wouldn't post much of a problem...
appears to be a *much* more lightweight approach. I have had some
Not at all. GHCi seems much faster because GHC's nontrivial startup overhead is amortized over the entire run.
I...see... I think... hmm...
Whatever... I'd just like to see an online way to run Haskell, and since the Lambdabot webpage still shows no sign of working...
That's my fault - I designed a much simpler configuration interface for lambdabot, but nobody has been motivated to un-bitrot GOA yet.
Um... what's GOA?

On Sunday 27 May 2007 06:05, Andrew Coppin wrote:
Um... what's GOA?
"GHCi on Acid": http://www.cse.unsw.edu.au/~dons/lambdabot.html Alexis.

Alexis wrote:
On Sunday 27 May 2007 06:05, Andrew Coppin wrote:
Um... what's GOA?
"GHCi on Acid": http://www.cse.unsw.edu.au/~dons/lambdabot.html
Ah, I see. I don't know about GHCi - I think the *lambdabot* logo looks like she's on something...!

Stefan O'Rear wrote:
On Sat, May 26, 2007 at 07:41:19PM +0100, Andrew Coppin wrote:
Donald Bruce Stewart wrote:
The #haskell people have been working on this for about 3 years now. The result is the 'runplugs' program, which I've talked about in previous mails.
http://www.cse.unsw.edu.au/~dons/code/lambdabot/scripts/RunPlugs.hs
It uses hs-plugins for the evaluation, along with the points about IO prevention via type checking, resource limits controlled by the OS, language extension preventions, and a trusted (audited) module base.
The security mechanisms were briefly described in the 2004 hs-plugins paper, if I recall, but otherwise, I don't think we've documented the techniques. Maybe we should, as many issues have been encountered over the years, further and further constraining the kinds of things that are allowed.
For me, the unfortunate thing is that there seems to be no interpreter for Haskell written in Haskell. (Except for GHC, which is *huge*.) We
Actually, there exists no interpreter for Haskell. Period.
Historical note: the first implementation of GHCi (by Alastair Reid) was a pure interpreter, IIRC. The second implementation, which was the predecessor to the current implementation, was also a pure interpreter, but we rewrote it to use a bytecode compiler/interpreter before it was ever released. The development history is all in darcs, if you care to take a look.. Cheers, Simon

On Sat, 26 May 2007, Andrew Coppin wrote:
This leaves only the problem of how to make a web server call GHC. I can think of a number of possibilities. - Write my own HTTP server from scratch. (Not keen...)
Hacking existing ones is easier: http://www.haskell.org/haskellwiki/Applications_and_libraries/Web_programmin...

On Sat, May 26, 2007 at 10:59:10AM +0100, Andrew Coppin wrote:
However, when you consider that the result type could be "IO ()" or "IO String" or "IO [Either (Maybe Int, (String, Bool)) [Either (Int -> String) (Complex Integer)]]", and the expression itself may well contain the "::" sequence... you see we have a nontrivial parsing task here! (Get the parsing wrong and somebody might be able to do Evil Things to the box.)
I think the easiest way to handle this would be to use the module system. just write a custom prelude that exports everything but 'IO' and don't allow arbitrary 'imports'. John -- John Meacham - ⑆repetae.net⑆john⑈
participants (16)
-
Alexis
-
Andrew Coppin
-
Brandon S. Allbery KF8NH
-
Claus Reinke
-
dons@cse.unsw.edu.au
-
Duncan Coutts
-
Gaal Yahas
-
Henning Thielemann
-
Ian Lynagh
-
Isaac Dupree
-
John Meacham
-
Neil Mitchell
-
Rodrigo Queiro
-
Simon Marlow
-
Simon Peyton-Jones
-
Stefan O'Rear