As more people start adopting Lispy languages, it will be important to build up a cultural awareness of what's dangerous. Things like not evaling code is obvious enough (I'd hope), but avoiding read less so. That seems less like "avoid eval" and more like "avoid gets".
You feel vindicated over this vacuous comment article? Let me sum it up for you: "It turns out if I set a safety variable, then unset it in a way that most of my audience won't recognize as assignment, I get votes up on hackernews."
Cultural awareness of read-time evaluation is as frustratingly absent now as it has always been; same as strcpy vs. strncpy. The only difference now is that we have increasingly more programmers with very little experience in charge of large software projects.
The people on HN are a big part of those defining the future of Clojure and other languages, so I'm glad to see an article like this raise awareness of something that will bite many as Clojure grows. Lines like these suggest the set-then-unset bit is part of a broader issue:
;; By a weird coincidence this week I wanted to read a file of data
;; coming from a web app, and I was about to use Clojure's reader to
;; do it.
It's disappointing to see that some Clojure practitioners are more interested in downvoting my comment and minimizing that issue rather than educating people about it.
I didn't downvote your comment, but I hold your sentiment in low esteem.
We don't stress over this for the same reason we don't stress over strlen-style errors. They're considered part of the basic education for the language. If someone does do this, they are operating below the expected standard for the language.
There is only so much a language and environment can be expected to do for you. Your understanding of trivial concepts like, "Loading code from untrusted sources is dangerous" is not an unreasonable bar to set. It is only an "issue" if you are fundamentally misinformed about writing software in interpreted environments.
It's bizarre that you can think something is "the expected standard for the language" but also not worth pointing out. How are people supposed to learn it?
There are incompetent programmers that no effort can reach, sure, but there are also junior programmers who are just innocent and haven't yet learned all the implications of what they're doing. I think it's important to teach these people, whether re Ruby or C or Clojure or whatever. That people treat such teaching with disdain makes me think they are misled by their defensiveness. It's not an insult of Clojure to say that (as in any language) there is stuff worth warning people about.
By understanding the halting problem and the implications thereof? This is not Clojure-specific, it's part of any dynamic eval tool.
> It's not an insult of Clojure to say that (as in any language) there is stuff worth warning people about.
This argument might hold some water if the presentation of the information was not couched in a different way. It is clearly not that. And you are clearly more concerned with being right than teaching people, from the words you are choosing to use.
Keep in mind that this is a Clojure-specific issue. In Common Lisp, eval-suppressing macros should prevent this sort of thing (but I would not rely on that -- it is easy to accidentally create a reader macro that fails to check those variables).
Personally, I would only use something like read if I were reading a configuration file i.e. something that only someone with privileged access can modify. I would not even consider using read for arbitrary, untrustworthy data; it is just silly in this day and age. It may make the code look prettier, but the fact that arbitrary data structures can be created and the potential to execute arbitrary code is enough to keep me away.
It's true that in general, people need to understand what is dangerous in each language they use.
However, as far as I can tell, the problem here has nothing to do with homoiconicity. The "get string" vulnerability, as you call it, comes out of Clojure's (excellent) JVM support, and not from the Lisp side of its family tree. A "read" is not just a read only because reading Java means creating and compiling arbitrary classes and objects. That, in turn, is largely because Java is not homoiconic.
> That seems less like "avoid eval" and more like "avoid gets".
Assuming that by `gets` you mean Ruby's `gets`, this is not quite right. `read` (and `read-string`) are not just generic IO functions. They are parsers for Clojure code. There are plenty of other varied forms of reading input to a string, but `read` does more.
Sorry, by "gets" I meant gets(3) from C, which probably seems like a perfectly valid way to read input to a new programmer, but is a sure way to give yourself a buffer overflow. My point was that some innocuous-seeming functions are traps, and it's important that knowledge of those traps become part of a language's cultural knowledge, in hopes that it reaches more developers.
But whether Ruby or C, I take your point that Clojure's read is not just an IO function. It's not really the IO-ness of gets that I'm trying to parallel, but its apparent safety. But perhaps to a Clojure programmer, read is not as surprising as gets because it's more clearly an evaling call. Do you think that'd be clear to a first-year Clojure dev?
I can't really speak to what is clear or not for a first-year Clojure dev. When I first learned Clojure, I had already dabbled in Lisps and Schemes for a while. The very first time I ran across `read`, probably in Scheme, it was obvious to me that it was special. Did I understand and appreciate the security implications? Probably not.
Hopefully the security issues will be clear to a new Clojure dev since at least the ClojureDocs site steers you away from read and towards EDN. Maybe the official docs should be more stern and clear about it, but they do make a note of the security issue: http://clojure.github.com/clojure/clojure.core-api.html#cloj...