Perl Toolchain Summit 2024
今年は Japan Perl Association が4月末にリスボンで開催された Perl Toolchain Summit のスポンサーについてくださったということで、久しぶりに日本語の記事も用意します。細かなことまで興味のある方は英語版のレポートもあわせてご覧いただければとおもいますが、ざっくり本年の成果を説明しますと、
- Perl 5.37 で導入された class 宣言を PAUSE が認識できるようにしました。
- PAUSE にアップロードしたモジュールがインデックスに掲載されない事件の原因となっていたデッドロックの問題を解消してきました。
- 将来の Perl や PAUSE の開発に関する議論などに参加してきました。
class 宣言については、2000年に Perl 6 の構想が発表されてからというもの、MooseX::Declare を代表とするいくつかの実験的なモジュールが独自の実装を行ってきましたが、 Perl 5.37 で class キーワードが実験的な機能として実装されたのを受けて、 feature プラグマ(や、experimental プラグマ)で有効になる class キーワードと、その試験的な実装である Object::Pad 、互換性維持のための Feature::Compat::Class による class キーワードのみを正当なクラスとして認識するようにしました。過去の記事や発表では、class キーワードを使ったモジュールを CPAN にアップロードする際には package 宣言も必要になるという話をしましたが、今回の修正で package 宣言がなくてもモジュールのバージョンを適切に取得できるようになります。
デッドロックの件については、直接的には上記の修正にあたって CPAN ミラーから PAUSE のデータを復元して 02packages という索引を生成する際の障害となっていたので手を入れたのですが、この修正によって、近年増えてきていたモジュールが正しく登録できなかったり権限が落ちたりしていた問題が改善していくものと期待しています。
なお、既存のデータについてはまだ検証が済んでいません。こちらでも今後時間を見つけて調べる予定でいますが、アップロードしたはずなのに最新版が MetaCPAN に出てこない等の問題が確認できた場合は、 PAUSE にアクセスして force_reindex していただけると助かります。
Perl の将来に関する議論についてはまた機会を見てまとめようとおもいます。PAUSE については新しくメーリングリストが作られ、Toolchain Summit 後も多少なりと継続的に活動していこうという話になりました。
その他、現地で関わったり議論したりしたこととしては、
- PAUSE のサーバが新しくなりました。昨年始めた docker 対応については宙ぶらりんになっていますが、関心がある方がいるようでしたら再度調整しようとはおもっています。
- PAUSE の MFA 対応は先送りになりました。現行の PR が入る可能性はありますが、来年以降、 Basic 認証ではない方法でも PAUSE にアクセスできるようにしていく過程で再実装しようと目論んではいます。
- CPAN Security グループが cpanm などの CPAN クライアントのデフォルトをセキュアにしようという活動を進めています。 cpanm については https://github.com/miyagawa/cpanminus/pull/674 で議論が行われたあとしばらく止まっているようですが、Perl 本体の SSL サポート等ふくめて今後の動向に注目しています。
- 同じく CPAN Security がらみで、 CPANTS にサイバーセキュリティがらみの対応が入っているかどうか等の基準を追加してはどうかという提案を受けました。具体的なところが見えていないので実装は先のことになりそうですが。
- Toolchain Summit にも新しい人を呼ぼうという動きが始まっています。実際、今年は新規参加者が四名もいましたし、招待候補者リストの中には日本の方も数名混じっていました。興味がある方がいらしたらお声がけくださいませ。
今回も多くの方のお世話になりました。あらためて主催の Breno Oliveira 、 Philippe Bruhat 、Laurent Boivin 各氏、以下のスポンサー各社・各氏にお礼申し上げます。
Monetary sponsors: Booking.com, The Perl and Raku Foundation, Deriv, cPanel, Inc Japan Perl Association, Perl-Services, Simplelists Ltd, Ctrl O Ltd, Findus Internet-OPAC, Harald Joerg, Steven Schubiger.
In-kind sponsors: Fastmail, Grant Street Group, Deft, Procura, Healex GmbH, SUSE, Zoopla.
JSON::XS 4.0の変更点と、それにともなうJSON、JSON::PPの変更について
これはPerl Advent Calendar 2018 7日目の記事です。
tl;dr
先日リリースされたJSON::XS 4.0が2013年に行われたJSONの仕様変更に追随したので、decode_json($json) の結果はかならずしもリファレンスではなくなりました。encode_json($value) にもリファレンス以外の値を受け入れるようになっています。結果、JSONモジュールの挙動がバックエンドによって異なる状態になり、各地でテストがこけるなどの影響が出ました。これを受けてJSON、JSON::PP側も変更に追随しましたが、みなさまの方でも適宜ご対応をお願いします。
2018年11月16日付けでJSON::XSのバージョン4.0が出ました。3.0が出たのが2013年10月29日のことですから、5年振りの大型アップデートということになります。今回の目玉は二点。いずれもこの数年界隈で何度となく話題に上がっていたものです。
allow_nonrefがデフォルトで有効に
配列やハッシュにくるまれていない素のスカラーを受け付けるallow_nonrefというオプションは2007年にJSON::XSがリリースされた当初から存在していたのですが、これはあくまでもRFC4627 (2006年)に対する拡張の扱いで、デフォルトでは無効になっていました。
その後、2013年にRFC7158が出てJSONの仕様が変わり、素のスカラーもJSONの値として有効なものとなりますが、JSON::XSは(そしてJSON、JSON::PPも)セキュリティ上の懸念があるとしてこの仕様変更には追随しませんでした。JSON、JSON::PP側にも仕様変更に追随するよう問題提起されていましたが、もちろんJSON::XS側にも同じような要請はあったのでしょう。2016年にリリースされたJSON::XS 3.02では新旧の仕様に関してわざわざドキュメントに一節を設け、
JSON::XS will not allow scalar data in JSON texts by default
と態度表明をしていました。だから、私自身この変更を見たときにはかなり驚いたのですが、よく見てみると、その節の最後にはこのような留保も書いてありました。
future versions might/will likely upgrade to the newer RFC as default format, so you are advised to check your implementation and/or override the default with ->allow_nonref (0) to ensure that future versions are safe.
そして今回、この助言に従っていなかったモジュール、アプリケーションが仕様変更の影響を受けている、ということになります。
もっとも、問題になっているといっても、今回の変更はこれまでエラーとなっていたJSONやデータを受け付けるようになった、というもの。互換性のためにあえてそのようなデータ/JSONがエラーになることを確認するテストを書いていた場合、あるいはソケットなどを経由して垂れ流したJSONデータをインクリメンタルパーサーでデコードしていたという場合はともかくとして、一般的な用法の範囲内では、既存のデータ、既存のJSONが受け付けられなくなる、ということはありませんので、まずはご安心をば。
ただ、デコード時のエラーチェックが不足していたり、デコードしたデータがかならずリファレンスであると仮定しているようなコードでは、想定外の入力が入ってきて予期せぬエラーが発生することがありえるのでご注意ください。
既存の挙動を変えたくない場合は、encode_json/decode_jsonのようなラッパーをそのまま使うのはやめて、JSON::XS->new->utf8->allow_nonref(0)->encode/decodeのようにするか(もちろん可能ならJSON::XS->new->utf8->allow_nonref(0)の部分は何かの変数にキャッシュしておくべきでしょう)、いっそのことJSON::XS/JSON::PP 4.0に明示的に依存するようにして、テストもallow_nonrefが有効になっていることを前提にするのもありかと思います(4.0より前のJSON::XSはすでにCPANから削除されているため、明示的に指定しない限り、JSON::XSに依存しているモジュールがあれば現状ではJSON::XS 4.0がインストールされます)。
この変更によって、かれこれ三週間ほどJSON 2.97001のテストがこけ続け、CI環境や各種スモーカーを運用しているみなさまにはご迷惑をおかけしていたのですが、これを機にJSONおよびJSON::PPも同様にallow_nonrefを有効にした4.0をリリースしました。一部の界隈からはJSON::PPまで上げる必要はなかったのではないかという声も聞こえてきますが、そもそもJSON::PP側が待っていたのはJSON::XSが仕様変更に追随していなかったからですし、JSON::XSとJSON、JSON::PPのメンテナ間ではなるべくお互いの互換性を維持しようという合意もできているので、この後に及んでJSON::PPだけあえて十年以上昔の古い仕様にこだわり続ける理由もないと思っています(この年末の忙しいときにこんなことはしたくなかったという思いはありますが、このタイミングを逃すと今度はPerl 5.30のコードフリーズが来るんですよね…)。
なお、JSON 4.0は、テストに使うJSON::backendPPモジュールがJSON::PP 4.0相当になっているだけで、実際にはJSON::XS 2〜4、JSON::PP 2.90〜4のいずれがバックエンドになっても動作します(Cpanel::JSON::XSも一部の非互換部分を除いては動作しますが、推奨しません。Cpanel::JSON::XSを使うのであれば、ラッパを使わず直接使うことをおすすめします)。
また、本項執筆時点ではCpanel::JSON::XSは今回の変更に追随していません。そのため、JSON::MaybeXSを利用して互換性のテストを行っているモジュールの中にはこの影響を受けてテストがこけているものが出ているかもしれません(メンテナ陣には問題が伝わっているので、この週末には必要に応じてなんらかの対策が取られるかもしれませんが、現時点でははっきりしたことはお伝えできません)。また、Cpanel::JSON::XSは後述するまったく別の理由で独自にバージョン4にしてしまったため、現状Cpanel::JSON::XSとJSONを共用している方は、この変更の有無をバージョンからは簡単に判別できない状態になっています(JSON::XSとJSON::PPはメジャーバージョンと主要な機能の対応が取れているので、JSON->backend->VERSION >= 4で判別できるのですが、JSONのバックエンドがCpanel::JSON::XSになるとこの条件では正しく判定できません)。Cpanel::JSON::XSをご利用の方はご注意ください。
boolean_values
JSON::XS 4.0では新たにboolean_valuesというメソッドが導入されました。これはJSONをデコードしたときにtrue/falseの値を任意のオブジェクトに変更できる、というものです。
これは、JSON単体で使っている分には特に意味のない機能ですが、JSONでデコードしたデータをたとえば何か別のシリアライザに引き渡したいとき、このboolean_valuesであらかじめbooleanやData::MessagePack::Booleanのオブジェクトを渡しておくと、データ構造の中にtrue/falseがあったらJSON::PP::Booleanのオブジェクトではなく、該当のオブジェクトに置き換わるので、YAMLやMessagePackでそのままシリアライズしやすくなる、と。
もっとも、この機能が有効なのはデコードのときのみなので、booleanのようにJSON::PP::Booleanとの互換性がないモジュールの場合、該当のデータ構造をJSONに戻す場合はconvert_blessedなどのお世話になることになります。JSON::PP::Booleanと互換性のあるTypes::Serialiser(::BooleanBase)やData::Boolのオブジェクトの場合はデコードで取り出したデータをそのままエンコードに回せます。
共通のブーリアンオブジェクトは欲しいけど、JSONじゃないものにまでJSON::PP::Booleanを使うのはなあ、という方はぜひ一度お試しください。
PERL_JSON_PP_USE_B環境変数
以前、YAPC::Hokkaidoの前夜祭でJSON::PPの数値判定処理を変更する実験的なパッチを受け入れたという話をしました。このパッチはPerl 5.27.1で一時的に(Perl側の変更のせいで)動作しなくなるなど、いささか微妙な性質のものなのですが、この変更によってJSONの出力が完全に一致するか確認するテストが壊れてしまうという苦情が届いていました。だいぶ今更ではあるのですが、状況を改善するため、JSON::PP 4.0ではPERL_JSON_PP_USE_B環境変数が真の場合は旧来のBモジュールを使った数値判定を行うようにしてあります。
Cpanel::JSON::XS由来の警告を無効に
Cpanel::JSON::XSが読み込まれた状態でJSON::PP(::Boolean)を読み込むと長らく警告が出るようになっていた(Cpanel::JSON::XS側はその警告を殺してJSON::PP::Booleanの挙動を差し替えていた)のですが、いい加減うっとおしくなっていたのでJSON::PP側でも警告を殺すようにしました。ロード順でJSON::PP::Booleanの挙動が変わるのはあまりうれしいことではないのですが、ふつうに真偽値としてのみ使ってくださる分には影響ないはずです。
番外
同じバージョン4.0つながりということでもうひとつ。今回JSONのテストを修正していてハマったことのひとつに、Cpanel::JSON::XS 3.99_01で導入されたCpanel::JSON::XS::TypeによってCpanel::JSON::XSのencode_jsonのプロトタイプが変わり、以下のようなテストが死ぬようになったことがあげられます。
ok ('[5]' eq encode_json $j1, "cjson1");
encode_json($j1)のように明示的にかっこでくくればよいだけの話ではあるのですが、ふだんからプロトタイプを利用してencode_jsonのかっこを省略している方は頭の片隅に入れておいていただければ。
というわけで、いろいろ大変なJSONまわりですが、今回4.0がらみで変わったところをまとめておきました。APIサーバなどでいずれかのモジュールをご利用の方も多いと思いますので、みなさまの方でも必要に応じて適宜ご対応いただければさいわいです。
明日は yukikimoto さんです。
London Perl Workshop 2017に行ってきた
tl;dr: It was really awesome (again)! A big thank you to the organisers and the speakers and everyone.
遅ればせながら、2017年11月25日にロンドンで開催されたLondon Perl Workshopに行ってきました。他の方の資料やビデオもそのうち公開されていくとおもいますが、とりあえず以下にLTの発表資料を置いておきます。2016年のヤパチーで話したPerl::PrereqScanner::NotQuiteLiteが大分いい感じになったので、そのうちCPANTSのチート対策します、という話(なぜかNotQuiteLiteという名前が想定外にウケたらしく、話している途中で何かやらかしたかとずいぶん戸惑ったものでした)。
NQLについては、発表駆動開発で当時できていなかったことの大半はできるようにしましたが、まだだいぶ遅いですし(一部の例外的なモジュールの解析にはPerl::PrereqScannerの倍以上かかったりする)、もう少し自由度を上げられるようにしないと自分自身が困るので、ドキュメントの更新ともども、時間ができたらなんとかしたいとおもっています。
おまけとしてTest::CPANfileというのもでっち上げました。テストするより都度更新した方が便利な場合も多いとはおもいますが、いろいろな理由でMinillaなどに移行できていない方には役に立つかもしれません。
WEB+DB PRESS Vol.100
8月24日発売のWEB+DB PRESS Vol.100に、Perl Hackers Hub連載の第46回として「Perl 5.26で変わること」という記事を書きました。タイトルからもおわかりの通り私のはこれまでYAPC::Hokkaido、YAPC::Kansai、YAPC::Fukuokaで話してきたことの焼き直しですが、100号記念ということで力の入った記事が多いのでぜひお手にとってみてください。
- 作者: 河原一哉,白土慧,菊田洸,西鳥羽二郎,柄沢聡太郎,大谷勇毅,新井啓太,HANADA Yoshihito,増田謙一,池上達也,木下祐実,藤原大,長野雅広,樫田光,縣俊貴,大川徳之,栗林健太郎,小飼弾,庄司嘉織,鈴木勇介,高橋征義,田中哲,徳永拓之,中嶋謙互,中島拓,西尾泰和,西田圭介,羽生章洋,藤本真樹,外村和仁,まつもとゆきひろ,松本亮介,ミック,三宅陽一郎,森田創,山本陽平,吉羽龍太郎,牧大輔,石垣憲一,平原正裕,ひげぽん,WEB+DB PRESS編集部
- 出版社/メーカー: 技術評論社
- 発売日: 2017/08/24
- メディア: 大型本
- この商品を含むブログ (1件) を見る
YAPC::Fukuokaに行ってきた
遅ればせながら、YAPC::Fukuokaに参加してきました。発表資料は以下の通りです。今回はPerl 5.26がリリースされたこともあって、前回、前々回の分から5.24の内容を削り、その分5.26のやや細かい話や、開発が始まったばかりの5.27系の話を追加しました。調べ物の過程でふたつほど5.26.0のバグを踏んだりもしましたが、いずれも次のリリース時には直る見込みです。準備の時間が足りず掘り下げきれなかった部分もありますが、その辺はまたいずれ何かの機会に。
JPAはじめスタッフ、スポンサーのみなさま、ありがとうございました。Okinawaも楽しみにしています。
'.' in @INC問題とその対処法について(2017年3月版)
YAPC::HokkaidoやYAPC::Kansaiで話した通り、Perl 5.26ではセキュリティ上の問題で@INCにカレントディレクトリが含まれなくなります。p5pやツールチェーン側ではその影響を軽減すべくCPANクライアントやTest::Harnessに従来の挙動を残すような仕組みを用意中ですが、現時点ではまだすべての対策が出そろっているわけではありません。最終的にどうすべきかは5月に開催される予定のPerl Toolchain Summit (旧Perl QA Hackathon)後にあらためてまとめるつもりですが、直接的な影響を受けるCPAN Authorのところには順次バグレポートが届いているかと思いますので、可能であれば以下の対応をご検討ください。
incディレクトリなどにMakefile.PL/Build.PL用の特殊なモジュールなどを同梱している場合
カレントディレクトリが@INCから消えることで、開発時および手動インストール時にはinc::Module::Install、inc::MyBuilderなどの同梱モジュールが正しく読み込めなくなる可能性があります。この辺は別途パッチがあたる可能性もありますが、基本的にはMakefile.PL/Build.PLなどの先頭付近に適宜以下のような行を追加しておいていただけると面倒がなくてよいかと思います(通常のインストール時にはCPANクライアント側で対策が取られるので問題にはならないはずです。また、どうせ開発するのは自分だけだから、perl -I. Makefile.PL/Build.PLするよ、という方もひとまず気にしなくてかまわないかと思います。ただ、CIがこけたりCPAN Testersなどから指摘を受ける可能性はあります)。なお、Makefile.PL/Build.PL については use lib "."; でもよいはずですが、今回の「対策」と呼ばれるものは "." を狙い撃ちにしているので、場合によってはおかしな副作用に巻き込まれる可能性があります。
use FindBin; use lib $FindBin::Bin;
また、Module::Installについては、Perl本体あるいはツールチェーン側で何らかの特別対応が行われる可能性もあるのですが、最新のModule::Installにも警告が出ている通り、これまでにもいろいろと問題が出ていますので、特に最新版をお使いでない方は、可能であればこの機会にMinilla、Dist::Zilla等のオーサリングツールに移行しておいていただけると助かります。
テストファイル中で t::Foo のようなモジュールを呼んでいる場合
これも、面倒でなければ、上と同じく各テストファイル中でFindBinを呼んで、実際の階層に応じたlib設定をしておいてください。
また、修正すべきファイルが多すぎて大変な場合は、依存モジュールにTest::Harnessの3.38以降を加えておけば、とりあえずmake test時には@INCにカレントディレクトリが戻るようになります。
これも同じくどうせ自分だけだから…という考え方もありですが、Makefile.PL/Build.PLの場合と同様におそらくCIでこけたり、CPAN Testersから指摘を受けることになるかと思います。
do "localfile.pl" のような呼び出しをしている場合
CPANモジュールには少ないと思いますが、お手元のアプリやスクリプトで環境設定などのために do を使ったファイル読み込みをしている場合は do "./localfile.pl"; のように明示的にディレクトリを追加しておいてください(もちろんFindBinを利用してもかまいません)。
また、require "jcode.pl"; のような行も、あれば同様の修正をお願いします(もっとも、jcode.plについてはそのままだとそもそも5.26では読み込み時にエラーになりますが)。
スクリプトをインストールするディストリビューションの場合
インストール時に bin/foo(.pl) のようなスクリプトをインストールするディストリビューションについては、追加の対策をしておいた方がよいかもしれません。コアに入っているものについてはいまのところスクリプトの先頭付近に以下のような行が追加されていますが、これについてはno lib "."; の方がよいという異論もあります(no lib "." なら明示的な perl -I. も封じることができますが、-I オプションを使える状況ならどちらにしても迂回できるので現状ではそれほど違いを気にする必要はないかと思います)。
BEGIN { pop @INC if $INC[-1] eq '.' }
なお、この行は基本的にはスクリプトやアプリの先頭付近に一度追加すれば十分です。
やってはいけないこと
use lib "."; は探索パスの「先頭」にカレントディレクトリおよび関連ディレクトリを追加してしまうので、うかつに使うとかえって発端となった脆弱性の影響を受けやすくなってしまいます。私的なスクリプトなどの応急処置には便利ですが、一般に公開するモジュール、アプリなどでは使用を避けてください。シェルスクリプト/バッチファイルなどから呼び出すperlのコマンドラインオプションに「-I.」を追加するのも同様の理由で危険です。
なお、CPANモジュールを使うだけの方は、5月のPerl Toolchain Summit以降にCPANクライアント(とTest::Harnessあたり)を最新にしておいていただければ、ほぼ問題なく5.26に移行できる(ようになる)見込みです。
YAPC::Kansai 2017に行ってきた
だいぶ遅ればせながらYAPC::Hokkaidoに引き続きYAPC::Kansaiも前夜祭から参加してきました。前夜祭についてはあいにく資料はありません。msysもcygwinも(ものによってはgnuwinのツール群も)入っていることとか、変換キーが「\」(カナ入力時には「ー」)、無変換キーがカナのオンオフ、半角/全角キーがエスケープになっていることとか、VMだけでなくWindows環境にもいちおうrakudoもgolangもnodejsもrubyもpythonも(もちろん複数バージョンのVisual Studioも)入っていることとか、話すつもりでいたことをもろもろ話し忘れたような気がしますが、誰得情報ということでご勘弁ください。ダイヤモンドカーソル依存やタッチパッドを無効にしている件も含めて、まっさらなノートPCを渡されると場合によってはものすごく困るクラスタに属しています。
本編の資料は以下の通りです。Perl 5、Perl 6ともに新しい安定版のリリースがあったわけではないのでHokkaidoからの引き写しも多いのですが、連続参加の方にも多少なりと新しい情報をお届けできるよう、Hokkaido以降に目にしたコメントなどへのレスを追加したり、2月にブリュッセルで開催されたFOSDEM 2017で仕入れてきた情報を追加したりしておきました。@INC問題についてはいよいよみなさんのところにも行動を求めるバグレポートが届き始めたようなので、別途記事を書いておきます。
何はともあれ、JPAはじめスタッフ、スポンサーのみなさま、ありがとうございました。Fukuokaも楽しみにしています。