先月あたりに話題になっていたJavaの脆弱性について解説した記事を眺めてみたのでメモ。POCへのリンクもあるので文章で書かれたことがどういうコードになるのかがなんとなくわかりました。Exploits自分が理解できた(つもり)のは以下のとおり。脆弱性を利用するとこれらの制限を回避できてしまうようです。以下の2つを達成することで、任意のコードを実行できるようになるようです。利用しているようです。勉強がてらこのライブラリを利用してHelloWorldプログラムを作成してみます。javaコマンドで実行してみます。Clojureで書いたコードと対応してるように見えます。}Clojureのコンパイル時の動作を詳しく知りたい場合、このライブラリを理解しておいたほうが良さそうです。ByteArrayInputStreamを作成することで、指定した文字列を読み込むことのできるReaderを作成できます。図にしてみようと思いました。clojure.reflectを使ってインターフェースの継承関係を取得し、DOTファイルを作って図にしてみます。DOTファイルとして保存します。DOTファイルをPNG画像にするには以下のコマンドを実行すれば良いです。interface-tree.pngシーケンスに関連する部分が多いようです。戒めの意味をこめてメモ。先頭2行がヘッダで残りの行がデータ、というExcelチックなファイルを読み込んでみます。読み込む対象となる大きなCVSファイルを作成します。(rand)))))CSVファイルを読み込んで指定した関数を実行する補助関数を定義します。指定された関数に渡される際にはまだ実際の読み込み処理は行われていません。r))))CSVファイルを表すLazySeqから、先頭行を取得してみます。ID4"]この処理は即座に終了します。LazySeqのおかげで、実際に読み込まれたのは500万行あるCSVファイルのうち1行だけ(のはず)です。ヘッダを表す先頭の2行を取得してみます。java.io.BufferedReader.ensureOpenこの処理は正常に終了しません。「ストリームが既にクローズされています」という例外が発生してしまいます。返す値がLazySeqであるために起こります。その時になってから実際の読み込み処理が行われますが、このときにはもう(with-openによって)入力ストリームはクローズしています。この処理を正常に行うには、実際の読み込み処理をストリームがオープンしている間に行わなければなりません。読み込み処理を行いたいタイミングで、doallマクロで囲んだり、ベクタに変換したりしましょう。d"]]次に、ファイルの最終行を取得してみます。0.9433273177661132"]多少時間はかかりますが、正常に終了します。同様に、doseqで各行に対して処理を行うふりをしても、処理は正常に終了します。nildoseqで処理を行った後で、先頭行を取得してみます。spaceこの処理はメモリが足りないと言われて異常終了します。doseq中にGCでメモリを回収できないからだと思われます。保持する必要はないため、メモリが足りなくなることなく正常に終了します。ID4"]次に、先頭行だけでなく、先頭の2行(ヘッダ)を取得してみます。spaceこの処理は異常終了します。返す値がLazySeqであり、doseqの後までCSVの内容を保持しておく必要があるためかと思います。私はここで悩みました。「ヘッダを取得」という関数を作成したつもりでいたために返値がLazySeqであるということを忘れていました。巨大なデータを保持しなくても良いようにします。d"])ファイルに限らず、LazySeqで巨大なデータを扱うときは、処理の途中でGCできるかどうか気を付けようと思います。