3

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?

Reb.Cabin
  • 5,426
  • 3
  • 35
  • 64
  • 2
    Beware, 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 Answers1

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
  • 2
    I 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
  • 1
    Well, 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