「鹿児島Gopherの集い with Fukuoka.go#15(オンライン開催)」に参加&発表した
鹿児島Gopherの集い with Fukuoka.go#15 (オンライン開催) に参加した。
Fukuoka.goというコミュニティと鹿児島でGoに興味がある人たちを中継してわいわいやろうという企画。当初はペパボの福岡オフィスと鹿児島オフィスにそれぞれ集まって中継する予定だったけど、新型コロナウイルスの状況を鑑みてオンライン開催になった。
ぼくは『PHPで送ってるメールをGoで解析する』というタイトルで15分枠で話してきた。
資料:https://speakerdeck.com/akht/evaluate-php-mail-in-go
かいつまんで言うと「PHPのプログラムから送ってるメールの内容が知りたいからmb_send_mail()
の引数に渡してる値を静的解析してみました」という内容。
実験したリポジトリはこちら:akht/php-mailsend-detector
静的解析をするにあたって一番の難所であるASTを得る部分は幸い便利なものがあったのでそれを使った。
自分で書いたのは、ASTから以下のようなノードを抜き出して実際に評価する評価器(evaluator)もどきの部分。
mb_send_mail
の関数呼び出し- その引数として渡されている変数
- 変数の割り当て
- 識別子
ASTを構築する過程で上記のようなノードをメモっておいて、改めてASTを再帰下降法的にトラバースしながらmb_send_mail
の引数を評価していく。
このevalという関数がキモ:コード
最初はこんな感じの
<?php
$to = "mail@example.com";
$subject = 'This is a Subject';
$body = "This is a Body";
$header = "header";
mb_send_mail($to, $subject, $body, $header);
とてもシンプルなコードしか評価できなかった。
※「評価できる」というのは今回の場合「メールの件名と本文を取り出せる」ということで、例えば上記のPHPコードを評価するとこういう出力が得られる(そっけないけど)。
[件名]:
This is a Subject
[本文]:
This is a Body
最初はそんなもんだったのが、現状ではこれくらいコードも評価できる。
<?php
define("CONSTANT_SUBJECT1", "This ");
define("CONSTANT_SUBJECT2", "is ");
define("CONSTANT_BODY1", "Thi");
define("CONSTANT_BODY2", "a");
$to = "mail@example.com";
$subject = get_subject() . "a Subject";
$var = "hoge";
if ($var == "hoge") {
$body = CONSTANT_BODY1 . get_body1() . get_body2() . " " . get_body3();
} else {
$body = "fake Body";
}
$header = "header";
function get_subject() {
return CONSTANT_SUBJECT1 . CONSTANT_SUBJECT2;
}
function get_body1() {
return "s ";
}
function get_body2() {
$var = "i";
$var2 = $var . get_s();
return $var2;
}
function get_body3() {
$to3 = CONSTANT_BODY2 . " " . "Body";
return $to3;
}
function get_s() {
return "s";
}
mb_send_mail($to, $subject, $body, $header);
つまりこのあたりに対応してる。
- 変数に文字列を代入
- 変数に定数を代入
- 変数に複数回代入(自己代入含む)
- 関数を評価してその戻り値を使う
- 関数内のローカル変数を参照
- 文字列結合(式の評価結果の結合を含む)
- 中置式の評価
- if文による条件分岐
ここまでやって、ちょっとしたものにはなったかなぁという気もするけど、実用にはまだまだ遠い(そのあたりは発表資料にも書いた)。オレタチノタタカイハコレカラダ。
オンライン開催は聴衆の反応がほとんどわからなくて「これ声聞こえてるのか?」とか思って発表が多少ぎこちなくなってしまったかもしれないけど、とても楽しいイベントだった。他の発表もとても面白かったし、知らないことが多くて(というか知らないことばかりで)とても興味深かった。
今の状況が落ち着いたらぜひFukuoka.goに遊びに行きたいし、また鹿児島でもGoのイベントをやりたい。おつかれさまでした & ありがとうございました!
それと、(発表ネタのために)ひさしぶりにこういうコードを書いてみたけどめちゃくちゃ楽しかった。やっぱ自分はこのへんが好きなのかなぁ。