I'd like to send a clojure expression in a string to be evaluated at the receiver, which might be a web service written in compojure. For example, suppose I have the string "(* 7 6)", which I'd like to turn into '(* 7 6), which I can then pass to eval and get 42. This operation is trivial in JavaScript, but not quite sure how to do it in clojure. Hints?
Asked
Active
Viewed 307 times
3
-
2Beware, this would allow a web client (anyone on the internet) to execute arbitrary code in your web server process, such as redefining vars, shelling out, deleting files, etc. – Chouser Apr 09 '13 at 06:11
-
Got it. My application will authenticate and authorize the sender for full trust before allowing this operation. Alternatively, it will parse, analyze, and / or sandbox the injected code. – Reb.Cabin Apr 09 '13 at 12:10
1 Answers
5
This should do the trick:
(eval (read-string "(* 7 6)")) ;; 42
Or, for short:
(load-string "(* 7 6)") ;; 42

leonardoborges
- 5,579
- 1
- 24
- 26
-
2I feel like this should be mentioned here; beware that even if you don't call eval, read-string itself will evaluate code: ```(read-string "#=(clojure.java.shell/sh \"ls\")")``` – bmaddy Apr 09 '13 at 15:54
-
I didn't find documentation for the #= reader syntax. Would you be so kind as to explain it, please? This is a very important observation! – Reb.Cabin Apr 09 '13 at 16:39
-
I found the answer in the following SW question http://stackoverflow.com/questions/6427967/clojure-reader-macro. This is rather a big deal since it makes it impossible to prevent evaluation without writing my own reader and could ruin my plans to use clojure for safe injection. – Reb.Cabin Apr 09 '13 at 16:46
-
found here how to turn it off https://groups.google.com/forum/?fromgroups=#!topic/clojure/_QBcSXE2iuE – Reb.Cabin Apr 09 '13 at 17:32
-
1Well, I'm glad I mentioned it then. You'll probably also want to use [clojail](https://github.com/flatland/clojail) when actually executing the code. – bmaddy Apr 10 '13 at 03:20