Skip to content

Instantly share code, notes, and snippets.

@hatzka-nezumi
Created March 16, 2017 16:17
Show Gist options
  • Save hatzka-nezumi/5bab0d1eb69d85f6492b7cc2f289eba7 to your computer and use it in GitHub Desktop.
Save hatzka-nezumi/5bab0d1eb69d85f6492b7cc2f289eba7 to your computer and use it in GitHub Desktop.
I've edited this to remove interspersed conversations. Original: https://gist.github.com/timmc/bef7b066ebdd54eb26dc04431cbe66f6
freenode/#clojure on 2014-04-21:
amalloy sets 5 to be 2 using reflection, probably in PM with clojurebot:
(let [field (nth (.getDeclaredFields Long) 3)] (.setAccessible field true) (.set field 5 2))
19:10 < amalloy> justin_smith: i think ''lovecraft should contain (alter-var-root #'defmacro (constantly (fn [& args] `(quote ~(rand-nth '#{various lovecraftian horrors|)))))
19:11 < justin_smith> ouch
19:11 < amalloy> or something like it, anyawy
19:11 < justin_smith> yeah
19:11 < justin_smith> maybe ''necronomicon would be the better name for it
19:13 < amalloy> or you could mutate one of the interned Number instances
19:13 < amalloy> really there are a lot of deep horrors you could put into a lovecraft library
19:14 < justin_smith> indeed
19:16 < justin_smith> stack traces generated using https://github.com/prismofeverything/zalgo
19:17 < rasmusto> forgive me: z̷̼͖̰̜̣͛̂̚͟ạ̶̹͔็l̀̄͌̈̐ͫg̉̊̐͑ͮͦȏ̉̏̿̿ͩ̓ï̞̗͓̮̮͙̃̄̚z̞̗͍̃͆̐͆͊̄̚e͗ͣ̔ͣ
19:17 < arrdem> justin_smith: what have you done...
19:17 < amalloy> huh. clojurebot's sandbox allows you to actually do what i just said
19:17 < amalloy> ,5
19:17 < clojurebot> 2
19:17 < justin_smith> woah...
19:17 < amalloy> i'll go put things back together now
19:18 * arrdem flees in terror
19:19 < amalloy> uhhhhhh, i can't put it back. 5 is 2 now. even if you add 1 and 4 you get 2. so there's no longer a 5 to reset 5 to
19:19 < amalloy> hopefully clojurebot's regular sandbox-resetting takes care of that
19:19 < rasmusto> ,(dec 5)
19:19 < clojurebot> 1
19:19 < arrdem> amalloy: what have you done...
19:19 < rasmusto> seems to work
19:19 < arrdem> ,(+ 3 5)
19:19 < clojurebot> 2
19:20 < justin_smith> rofl
19:20 < justin_smith> ,(= 5 2)
19:20 < clojurebot> true
19:20 < justin_smith> ROFL
19:20 < arrdem> I don't even have a gif for this level of wat...
19:20 < justin_smith> (inc amalloy)
19:20 < lazybot> ⇒ 101
19:20 < rasmusto> ,(range 6)
19:20 < clojurebot> #<IndexOutOfBoundsException java.lang.IndexOutOfBoundsException>
19:20 < arrdem> AHAHAHAHA
19:20 < rasmusto> what
19:20 < arrdem> (inc amalloy)
19:20 < lazybot> ⇒ 102
19:20 < justin_smith> lol
19:20 < justin_smith> (take 10 (range 6))
19:20 < justin_smith> ,(take 10 (range 6))
19:20 < clojurebot> #<IndexOutOfBoundsException java.lang.IndexOutOfBoundsException>
19:20 < arrdem> amalloy: I want to see the source for this...
19:20 < arrdem> ,6
19:20 < clojurebot> #<IndexOutOfBoundsException java.lang.IndexOutOfBoundsException>
19:21 < arrdem> WHAT THE hahaha
19:21 < amalloy> oh, it's not hard. (let [field (nth (.getDeclaredFields Long) 3)] (.setAccessible field true) (.set field 5 2))
19:21 < rasmusto> ,7 ;plz?
19:21 < clojurebot> #<IndexOutOfBoundsException java.lang.IndexOutOfBoundsException>
19:21 < justin_smith> ,7
19:21 < clojurebot> #<IndexOutOfBoundsException java.lang.IndexOutOfBoundsException>
19:21 < amalloy> i think i broke all the numbers when i tried to put it back together
19:21 < rasmusto> ah okay.
...
19:22 < justin_smith> clearly the 'adams ns will turn every number up to N into 42
...
19:38 < gtrak> knr doesn't actually work... I'm making a note on the githubs :-)
19:38 < gtrak> it's half-completed
19:39 < justin_smith> hey, half-complete knr, complete footgun, who would know the difference except for a few symbols and filenames?
19:39 < amalloy> gtrak: 1/2 completed is the same as 1/5 completed, actually
...
19:40 < gtrak> amalloy: I think I'm missing something subtle there :-)
19:40 < gtrak> or is it 80/20?
19:40 < arrdem> also gtrak. meajure is now a thing. you're entirely to blame for the name.
19:40 < gtrak> hehe
19:40 < amalloy> gtrak: no, i was referring to my recent clojurebot hack
19:40 < justin_smith> gtrak: search up for ,(= 5 2)
19:40 < arrdem> ,(= 5 2)
19:40 < clojurebot> false
19:41 < arrdem> good. clojurebot is no longer horked
19:41 < rasmusto> ,(range 6)
19:41 < clojurebot> (0 1 2 3 4 ...)
19:41 < rasmusto> where's 5????
19:41 < TEttinger> rasmusto: ##(range 6)
19:41 < lazybot> ⇒ (0 1 2 3 4 5)
19:41 < justin_smith> ,5
19:41 < clojurebot> 5
19:41 < rasmusto> :)
19:41 < TEttinger> one of the bots trims output
19:42 < justin_smith> we were just kind of worried about 5 and hoping 5 was OK
19:42 < rasmusto> TEttinger: gotcha, was making a reference to ,(= (dec 5) 1) earlier
19:42 < TEttinger> heh wha
19:43 < justin_smith> probably the best clojure wat I have seen so far
19:43 < amalloy> i figured out how i broke clojurebot the second time
19:43 < justinholguin> ,(= (dec 5) 1)
19:43 < clojurebot> false
19:43 < justinholguin> phew
19:43 < amalloy> i was trying to set 5 back to 5, but instead i set 2 to 5. so looking up the third item in an array caused you to look up the sixth item instead. thus all the ArrayIndexOutOfBoundsException problems
19:44 < gtrak> how'd you do that in the first place? I didn't see it in the scroll-up
19:44 < TEttinger> ,(def 5 4)
19:44 < clojurebot> #<CompilerException java.lang.RuntimeException: First argument to def must be a Symbol, compiling:(NO_SOURCE_PATH:0:0)>
19:44 < justin_smith> another good name for an intentionaly messed up lib would be angkor (named for the world's biggest Wat)
19:44 < amalloy> gtrak: it's not hard. (let [field (nth (.getDeclaredFields Long) 3)] (.setAccessible field true) (.set field 5 2))
19:44 < justin_smith> gtrak: amalloy pasted it, by setting some properties of Long I think
19:44 < justinholguin> (inc justin_smith)
19:44 < lazybot> ⇒ 34
19:44 < justin_smith> oh, there it is again
19:45 < gtrak> ah, ye old integer cache
19:45 < justin_smith> probably will call for some new sandbox rules
...
19:45 < TEttinger> (let [field (nth (.getDeclaredFields Long) 3)] (.setAccessible field true) (.set field (rand-int 100) 101))
19:45 < TEttinger> ,(let [field (nth (.getDeclaredFields Long) 3)] (.setAccessible field true) (.set field (rand-int 100) 101))
19:45 < clojurebot> #<IllegalArgumentException java.lang.IllegalArgumentException: Can not set final long field java.lang.Long.value to java.lang.Integer>
19:45 < TEttinger> aw
19:45 < rasmusto> justin_smith: glad someone else shares my taste for puns
19:46 < amalloy> iit turns out you have to do a bit more work to set it back
19:46 < amalloy> (let [five (long (int (+ (int 1) (int 4)))), field (nth (.getDeclaredFields Long) 3)] (.setAccessible field true) (.set field five (int (+ (int 1) (int 4))))) ;; actually worked to recover my repl
19:46 < rasmusto> amalloy: is this idiomatic code?
19:47 < rasmusto> er, does it at least show how to use java interop properly?
19:47 < TEttinger> there's nothing proper here
19:47 < arrdem> rasmusto: do you see that crowbar? do you see it?
19:47 < arrdem> rasmusto: that's almost as [good|bad] as the reader macros with crowbars hack
19:47 < amalloy> sure, just like carrying a chainsaw with you at all times is the idiomatic way to get into doors you really shouldn't be getting into
... ... ...
... ... ...
... ... ...
14:21 < amalloy> gfredericks: were you around when i broke clojurebot by redefining 5 to be 2?
14:22 * llasram would like to see that...
14:22 < amalloy> llasram: it's not super-hard. you use reflection to modify the .value field of (Long/valueOf 5)
14:23 < technomancy> isn't this something we make fun of ruby for making possible?
14:23 < technomancy> I'll have to update my Tome of Mockery
14:25 < llasram> amalloy: Ah. Yeah, ok. IMHO using reflection to stomp on private final (I assume?) fields is basically the same as memcpy()ing
14:25 < llasram> So I'm somewhat less impressed :-)
14:26 < gfredericks> amalloy: no way that's nutso
14:26 < TimMc> :-(
14:27 < gfredericks> Tim does not like it
14:31 < llasram> Well, unless someone re-defined TimMc's smiley face to use ":-("
14:31 < llasram> At this point we have no real way of knowing
14:34 < hyPiRion> It's hard to know anything when everything is relative and changing.
14:35 < gfredericks> except the undeniable objective fact that it's hard to know anything when everything is relative and changing
14:37 < TimMc> amalloy: How's that?
14:37 < amalloy> how's what?
14:37 < TimMc> I did (.setAccessible (.getDeclaredField Long "value") true) but then this errors: (.setLong (.getDeclaredField Long "value") 5 2)
14:38 < hyPiRion> gfredericks: but then it's not hard to know anything, it's hard to know anything with the exception of that statement
14:38 < amalloy> TimMc: setAccessible mutates the Field object you have. you can't re-get the Field object
14:38 < TimMc> Oh! Point.
14:38 < amalloy> (doto (.getDeclaredField Long "value") (.setAccessible true) (.setLong 5 2)) or something
14:39 < ystael> amalloy: does that break just one five or all the fives?
14:39 < amalloy> all the (boxed) fives
14:39 < llasram> Oh, language
14:39 < amalloy> and since clojure boxes everything, that's all of them
14:39 < TimMc> ,(let [f (.getDeclaredField Long "value"), subject 5] (.setAccessible f true) (.setLong f subject 2) subject)
14:39 < clojurebot> 2
14:39 < TimMc> D-:
14:39 < hyPiRion> amalloy: not all the boxed fives?
14:39 < amalloy> TimMc: ugh, don't do it to clojurebot again
14:39 < llasram> ,(+ 5 5)
14:39 < clojurebot> 4
14:39 < hyPiRion> ,(Long. "5")
14:39 < clojurebot> 5
14:39 < TimMc> oops
14:40 < amalloy> hyPiRion: true. all the ones boxed via Long/valueOf
14:40 < TimMc> I should have use a bigger 5.
14:40 < arrdem> ,(+ 2 2)
14:40 < clojurebot> 4
14:40 < arrdem> ,(+ 5 5)
14:40 < clojurebot> 4
14:40 < ystael> is there a numerical threshold above which boxed instances are not cached and shared?
14:40 < jcromartie> wow, nice
14:40 < TimMc> ,(let [f (.getDeclaredField Long "value"), subject 5] (.setAccessible f true) (.setLong f subject 5) subject) ;; fixed?
14:40 < clojurebot> 2
14:40 < hyPiRion> ystael: 128 or 256 I think
14:40 < llasram> ,(+ 5 5)
14:40 < clojurebot> 4
14:40 < amalloy> ystael: +/- 128
14:40 < TimMc> hahaha
14:40 < amalloy> well, -128 to 127
14:40 < llasram> ,(let [f (.getDeclaredField Long "value"), subject 5] (.setAccessible f true) (.setLong f subject (Long. "5") subject))
14:40 < clojurebot> #<IllegalArgumentException java.lang.IllegalArgumentException: No matching method found: setLong for class java.lang.reflect.Field>
14:41 < arrdem> http://i0.kym-cdn.com/photos/images/newsfeed/000/613/012/2fa.gif
14:41 < hyPiRion> TimMc: You have seen nothing yet
14:41 < llasram> ,(let [f (.getDeclaredField Long "value"), subject 5] (.setAccessible f true) (.setLong f subject (Long. "5")) subject)
14:41 < clojurebot> 5
14:41 < TimMc> It restarts every 12 minutes, right?
14:41 < llasram> ,(+ 5 5)
14:41 < clojurebot> #<IndexOutOfBoundsException java.lang.IndexOutOfBoundsException>
14:41 < TimMc> And by 12, I mean 12.
14:41 < llasram> Hmm
14:42 < amalloy> llasram: that's the way i tried to fix it the first time
14:42 < amalloy> but you made the same mistake i did
14:42 < amalloy> instead of defining 5 back to 5, you defined 2 to 5
14:42 < llasram> Oh, right
14:42 < llasram> hah!
14:42 < hyPiRion> hahah
14:42 < amalloy> so now like every array access breaks
14:42 < TimMc> I <3 FORTRAN.
14:43 < amalloy> we never did find out if clojurebot's auto-restart actually fixes this problem
14:43 < llasram> *amazing*
14:43 < amalloy> hiredman gave it a manual hard-reset before waiting for that
14:43 < arrdem> amalloy: one way to find out...
14:45 < TimMc> ,(let [f (.getDeclaredField Long "value"), subject 0] (.setAccessible f true) (.setLong f subject 42) subject) ;; if it will even run...
14:45 < clojurebot> #<IndexOutOfBoundsException java.lang.IndexOutOfBoundsException>
14:45 < TimMc> ,(.getDeclaredField Long "value")
14:45 < clojurebot> #<IndexOutOfBoundsException java.lang.IndexOutOfBoundsException>
14:45 < TimMc> Amazing.
14:45 < amalloy> TimMc: right, it's too late i think. you can no longer eval anything
14:45 < amalloy> because eval uses the number 2 in an array somewhere
14:45 < amalloy> ,1
14:45 < clojurebot> #<IndexOutOfBoundsException java.lang.IndexOutOfBoundsException>
14:46 < TimMc> Got it.
14:46 < arrdem> hahaha
14:46 < hyPiRion> ,'1
14:46 < clojurebot> #<IndexOutOfBoundsException java.lang.IndexOutOfBoundsException>
14:46 < arrdem> (inc TimMc)
14:46 < lazybot> ⇒ 58
14:46 < TimMc> Only 28 points!
14:46 < TimMc> I thought I had more.
14:47 < hyPiRion> TimMc: well, since 2 is 5 and 5 is 2
14:47 < gfredericks> wait we can prove a contradiction with this right? and then derive anything?
14:47 < gfredericks> let's derive bugfixes
14:47 < arrdem> gfredericks: quick prove P!=NP then we can keep our jobs forever
14:48 < TimMc> amalloy: Do you know any way to get ahold of that interned 5?
14:48 < ystael> TimMc: it's no longer a number ... it's a free man now
14:49 < amalloy> TimMc: what do you mean?
14:49 < gfredericks> arrdem: or P = NP but only for galactic algorithms
14:49 < TimMc> Well, I'm trying to restore my REPL's notion of small numbers.
14:49 < arrdem> gfredericks: this is also an acceptable outcome.
14:49 < amalloy> i don't think you can do it if you've gone to the second level of broken like llasram did
14:50 < amalloy> but if you've only broken it one level, it is reversible
14:50 < TimMc> Just one level of fail.
14:50 < amalloy> iirc this works: (let [five (long (int (+ (int 1) (int 4)))), field (nth (.getDeclaredFields Long) 3)] (.setAccessible field true) (.set field five (int (+ (int 1) (int 4)))))
14:51 < TimMc> I'm having trouble figuring out what's going on here: https://www.refheap.com/85696
14:52 < amalloy> fiddling with (Long. "5") doesn't help, because that's not the interned version
14:52 < TimMc> Oh! Right-o.
14:52 < llasram> Wouldn't (Long/valueOf "5") work? Or does the compiler do funny things?
14:52 < amalloy> &(identical? (Long/valueOf "5") 5)
14:52 < lazybot> ⇒ false
14:52 < llasram> Oh, interesting
14:52 < amalloy> &(identical? (Long/valueOf 5) 5)
14:53 < lazybot> ⇒ true
14:53 < llasram> That makes sense of course
14:53 < amalloy> i don't know *why*, but apparently the string version bypasses interning
14:53 < amalloy> llasram: does it? it should parse it as a long, then use the intern cache to get a Long
14:53 < TimMc> valueOf probably just shortcuts, right?
14:54 < amalloy> incidentally, three cheers for repl history: i just searched it for setAccessible to find this fix; i probably wouldn't have remembered it on my own
14:55 < llasram> amalloy: Eh. It's not really clear to me why it should use the cache for the result of string parsing. Not saying it shouldn't -- it just doesn't seem unreasonable for it to not
14:55 < hyPiRion> TimMc: Oh hey, if you find this sort of stuff funny, you should see this one: https://www.refheap.com/85697
14:56 < hyPiRion> That one segfaults or makes your JVM spin up an infinite loop
14:57 < amalloy> hyPiRion: do you really have to remove its FINAL modifier? once you make it accessible i think you can already write to it
14:57 < amalloy> just like for Long
14:57 < amalloy> maybe you're doing something weird i don't see there
14:59 < hyPiRion> amalloy: it's static, which makes it a bit different IIRC
14:59 < hyPiRion> at least I just checked, and it doesn't work with just .setAccessible
15:00 < TimMc> ,(+(*)(*)(*)(*)(*))
15:00 < clojurebot> 5
15:00 < TimMc> It's back!
15:00 < llasram> ,(+ 5 5)
15:01 < clojurebot> 10
15:01 < llasram> Yay!
15:07 < TimMc> amalloy: I was able to fix it in my REPL by using "subject (+ 2 3)", but when I tried again with "subject 5" nREPL quit with an NPE. :-P
...
15:10 < amalloy> TimMc: yeah, that's setting 2 to 5 again
15:10 < amalloy> which really is a lot more disruptive than setting 5 to 2
... ... ...
... ... ...
... ... ...
13:48 < justin_smith> ,(let [field (nth (.getDeclaredFields Long) 3)] (.setAccessible field true) (.set field 5 2))
13:48 < clojurebot> nil
13:48 < justin_smith> ,(inc 5)
13:48 < clojurebot> 3
13:48 < andyf> You can break the JVM's 5, but Plato's 5 is safe in the world of forms
13:48 < justin_smith> haha
13:48 < gfredericks> ~5 is the set of all sets with 5 elements
13:49 < clojurebot> Ik begrijp
13:49 < bbloom_> , (.getDeclaredFields Long) 3)
13:49 < clojurebot> #<Field[] [Ljava.lang.reflect.Field;@5753b0>
13:49 < bbloom_> ,(.getName (.getDeclaredFields Long) 3))
13:49 < clojurebot> #<IllegalArgumentException java.lang.IllegalArgumentException: No matching method found: getName for class [Ljava.lang.reflect.Field;>
13:49 < bbloom_> ,(.name (.getDeclaredFields Long) 3))
13:49 < clojurebot> #<IllegalArgumentException java.lang.IllegalArgumentException: No matching method found: name for class [Ljava.lang.reflect.Field;>
13:49 < bbloom_> ,(clojure.reflect/reflect (.getDeclaredFields Long) 3))
13:49 < clojurebot> #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.reflect>
13:49 < bbloom_> ,(require 'clojure.reflect)
13:49 < clojurebot> nil
13:49 < bbloom_> eh wahtever... how do i get the name of a field?
13:49 < gfredericks> .getName?
13:49 < bbloom_> i tried that
13:49 < bbloom_> oh dur it's an array
13:49 < gfredericks> with 3?
13:50 < bbloom_> ,(.name (nth (.getDeclaredFields Long) 3))
13:50 < clojurebot> #<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: name for class java.lang.reflect.Field>
13:50 < bbloom_> i suck
13:50 < bbloom_> ,(.getName (nth (.getDeclaredFields Long) 3))
13:50 < clojurebot> "value"
13:50 < andyf> The world of forms: Bringing you real immutability since 348 BC
13:50 < bbloom_> ah ok i gotcha. boxed small numbers are interned
13:51 < justin_smith> , (nth (.getDeclaredFields Long) 3)
13:51 < clojurebot> #<Field private final long java.lang.Long.value>
13:51 < justin_smith> ,(.getName (nth (.getDeclaredFields Long) 3))
13:51 < clojurebot> "value"
13:51 < bbloom_> andyf: https://en.wikipedia.org/wiki/348_BC <- i was hoping you knew the actual year
13:51 < justin_smith> bbloom_: ^
13:51 < bbloom_> justin_smith: i got there eventually :-P
13:52 < justin_smith> bbloom_: aha, I missed it while I was finding it in my own repl
13:52 < andyf> Sorry, I don't know when he wrote about it first, so I approximated by the year Plato died.
13:53 < justin_smith> ,(= 5 3)
13:53 < clojurebot> false
13:53 < justin_smith> ,(= 5 2)
13:53 < clojurebot> true
13:53 < justin_smith> ,(let [field (nth (.getDeclaredFields Long) 3)] (.setAccessible field true) (.set field 5 (inc 4)))
13:53 < clojurebot> nil
13:53 < justin_smith> ,(= 5 2)
13:53 < clojurebot> true
13:53 < justin_smith> I thought I fixed that...
13:54 < justin_smith> ,(let [field (nth (.getDeclaredFields Long) 3)] (.setAccessible field true) (.set field (inc 4) (inc 4)))
13:54 < clojurebot> nil
13:54 < justin_smith> ,(= 5 2)
13:54 < clojurebot> true
13:54 < justin_smith> ,(inc 2)
13:54 < clojurebot> 3
13:54 < justin_smith> ,(inc 5)
13:54 < clojurebot> 3
13:54 < mearnsh> this is why we can't have nice things
13:54 < AeroNotix> ,(inc (+ 3 2))
13:54 < clojurebot> 6
13:54 < justin_smith> :( I forgot how to fix it
13:54 < AeroNotix> ,(inc 5)
13:54 < clojurebot> 3
13:54 < AeroNotix> 5
13:55 < AeroNotix> ,5
13:55 < clojurebot> 2
13:55 < justin_smith> ,(let [five (long (int (+ (int 1) (int 4)))), field (nth (.getDeclaredFields Long) 3)] (.setAccessible field true) (.set field five (int (+ (int 1) (int 4)))))
13:55 < clojurebot> nil
13:55 < andyf> Once you make 5 equal to something else, the JVM extrapolates and is able to prove that all numbers are simultaneously equal to, and not equal to, all others.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment