Hatena::ブログ(Diary)

Opensource days

2014-10-13

hhvm + hack > zend + php ?

PHPカンファレンス2014も無事に終わり、参加者も1000人超えとなるなど、大盛況でした。これだけイベントが大きくなるとメインのスタッフの方の負荷も相当なものだったと思います。大変お疲れ様でした。

プレゼンの時にも話をしましたが、今年はPHPNGを始めとして開発が活性化しつつあり、そのきっかけとなったのは、hhvm と HACK の公開だと思います。2010年のHipHop C++トランスレータ(HPHPc)の時は、そういう手法もあるのかなと思っていただけに近かったのですが、今回は少し違う印象を持っており、今後、その存在が一般に広く受け入れられると考えています。hhvmのサイトでプレゼンを見ただけでなく、今回Paulのプレゼンを直接みたり、彼と話をしてみて、その印象が大きくなっているところです。以下、少し考えをまとめてみたいと思います。(といってもあまりまとまっていませんが...)

f:id:rui_hi:20141011173546j:image:right

PHP開発プロセスの課題


Paulのプレゼンでも触れられていましたが、以前のHPHPcアプローチとの違い一つは、PHPアメンバーのSaraなどを雇い入れ、本気でOSSとして開発しているということです。Facebookのような営利企業が、重要な開発インフラを公開するというのは日本ではあまり考えられないような気がしますが、開発の速度・質を重んじる考えが受け入れられているのでしょう。

PHP本体の開発体制は、RFCについて投票に基づき採否を判断する民主主義的なプロセスに移行しています。以前の一部のコア開発者による開発プロセスと比較して、この仕組みの良いところは多様な意見を取り入れることができるところで、実際、他の言語では一般的だったにもかかわらず、PHPでは未サポートだった便利な仕様などが取り入れられていたりします。

一方、投票に基づく判断プロセスは、例えばプロリクエストをメンテナが採否を独断で判断する方式に比べて、客観性には優れるものの、時間を要し、煩雑になることになります。また、少数派であっても反対意見の方が強い傾向があり、有用な機能が受け入れられないこともあります。

Hackで取り入れられている型アノテーションは、PHPにおいてもかなり以前から議論され、実装が開発ブランチに入ったこともありましたが、取り消されています。PHPの型付けがどうあるべきか、という議論には、おそらく結論がないでしょう。PHP自体がこうあるべきであるという思想はあるにしても、その実現方法は一つではないからです。

hhvm+Hack登場の意味

hhvm + Hack の完成度と実用性は既に高く、特に開発力のある大手のサイトが移行に積極的になっているようです。そして、これを成功例として、より広範なWebサイトに採用されるようになるでしょう。

PHPエンジンの高速化は5.3から5.4にかけて劇的に進み、PHP 4.3の時以上に高速化が進んできましたが、昨今はもうやりつくされた感がありました。しかし、今年に入ってから、Zend開発陣も明らかにhhvmに刺激を受けてPHPNGを立ち上げ、大幅な性能向上を目指すなど、開発の動きが大幅に活性化しています。

PythonRubyなどと同様にPHPにおいても複数の処理系が存在する時代が来ているということになりますが、心配なのは互換性となります。その意味で「PHP Language Specification」を定めるというのは大きな前進と言えます。従来は、PHPの出力がundocumentedな部分でおかしくても実質的に仕様となってしまっていたのですが、今後は、そういった曖昧さを排除していく必要があります。PHPISOJISになるとは思いませんが、標準化されるというのは企業ユーザにとっても安心感につながるのではないでしょうか?

hhvm+hackにおいてやはり心配となるのは、私企業であるFacebookが自分たちのビジネスに必要なツールとして開発をしているところです。彼らは既にPHPの最新版である5.6にもとづいており、今後のバージョン更新にも追従していくと宣言しており、また、大幅な仕様変更が行われる場合には移行ツールを提供する言っているため、その心配が現実になることは実質的にないと考えています。

 もちろん、Facebookが10年後にまだ現在の活力を保っていられるかはわかりません。Facebook自体で継続が困難となった場合にも、ソースコードが公開せれているOSSのメリットにより、プロプライエタリな環境と比べて、開発資産を有効に活用することができる確率は高いと考えます。

hhvm+Hackに移行すべきか

hhvm+hackでサポートされる機能は、特に大規模開発において有用なものです。PHPは主に小中規模のWebサイトで使用されていると言われてきた時代がありましたが、Facebookのような世界最大級のWebサイト実用的に運用されていることを考えると、そうした見方は既に過去のものとなりつつあります。

種々の機能は、小中規模のWebサイトでも有用なものです。型アノテーションに加えて、非同期プログラミングについても実用例が多く公開されればその有用さが広く認知されるはずです。Webサーバの実行プロセスモデルとからんだりするのかもしれませんが、楽しみな機能の一つです。また、JITコンパイラについてもHotである(つなりJITコンパイルの対象とする)部分の判定や、最適化など、今後も話題になる部分があると考えます。

今回のプレゼンを準備する際、現在、PHP 7.0に提案されている機能リストを並べてみて、あらためて気づいたのは、その多くがhhvmで既に実現されていることです。これからPHP 7.0のリリースまでに1〜2年を要すると思われますが、hhvmが既にPHPの未来の姿であるとするならば、現時点で開発のプラットフォームを移行するというのもリーズナブルな選択肢と考えられます。

2012-11-23

mbstring.encoding_translation有効時にhashDoS脆弱性

すでに徳丸氏がTwitterでコメントされていますが、PHPの過去のバージョン全てにおいてmbstring.encoding_translationをOn(有効)にした際にmax_input_varsによる制約が無効になってしまうという問題がありました。max_input_varsはユーザ入力変数の最大数を指定するパラメータであり、hashDoS対策として導入されたものです。この結果として、mbstring.encoding_translation=Onの設定でhashDoS脆弱性が存在していました。

mbstring.encoding_translationはmbstringの機能で、ユーザー入力パラメータの文字エンコーディングを自動的に内部文字エンコーディングに変換する用途で使用されています。

昨日公開された最新のバージョン(PHP 5.4.9またはPHP 5.3.19)ではこの問題が修正されていますので、このバージョンへの早期更新を推奨します。

問題はなぜ気が付かなかったかということですが、メンテナの一人としてチェックが甘かったとしか言いようがありません。。。

2012-10-14

OAuth 2.0 が RFCに

長い間、ドラフトだったOAuth 2.0とBearer TokenがついにRFCになりました。

The OAuth 2.0 Authorization Framework

The OAuth 2.0 Authorization Framework: Bearer Token Usage

すでにGoogleFacebookを初め、ドラフト版に基づく実装が普及しているので、今後、更に普及することが予想されます。TwitterのようなOAuth 1.0に基づく実装の移行も進むかもしれません。

拙作のOAuth2用ライブラリLightOAuth2RFCベースに更新して、Composedしてみようかと思います。

個人的には、GoogleFacebookを始めとするOAuth 2.0 API実装例も豊富に解説されている拙書PHP徹底構築が売れるきっかけになってくれるとうれしいです(宣伝モード (^_-))。

2012-10-06 Scilab 5.4リリース

Scilab 5.4の新機能

Scilab の新バージョン5.4.0が2012年10月1日ついにリリースされました。機能強化のポイントについてまとめてみたいと思います。なお、Scilab 5.4の新機能の詳細については、YoutubeのScilabチャネルを参照ください。

Scilabデスクトップデフォルト

Scilab 5.4の目玉は、Scilabデスクトップと呼ばれる環境がデフォルトになったことでしょう。この種の機能は商用ソフトウエアであるMATLABでもずいぶん前から標準になっており、イメージは非常に近いものです。個人的には、従来のシンプルなコマンドウインドウが好きなのですが、GUI中心の操作での操作性は確実に向上するものと期待できます。変数ブラウザも5.3のシンプルなものに比べて機能強化おり、変数の型などがわかりやすくなっています。

f:id:rui_hi:20121006112532p:image

この他、「編集/プリフェレンス」メニューから各種の設定が行われるようになりました。

全般的な動作の高速化

ベンチマークをとったわけではありませんが、グラフィックスのレンダリング変数ブラウザ、一部の関数などの動作が全般的に高速化されています。体感的にも5.3に比べて高速化されている気がします。

CSVファイルの読込が高速化

この機能は、従来、別モジュールとしてAtomsでインストールする必要があったものをマージしたものです。従来の標準のCSV読み書き関数(read_csv, write_csv)は動作が遅かったのですが、今回導入された関数(csvRead, csvWrite)を使用すると、数10倍に動作が高速化されます。

v = csvRead("dat.csv"); // CSVファイルを読み込む

Scilab Open Data (SOD)形式がバイナリ保存形式の標準に

save関数による保存、load関数による読込時のファイル保存形式としては、従来は独自フォーマットが定義されていましたが、汎用のHDF5形式に基づくSOD形式が標準となりました。5.4では従来のバイナリ形式の読み書きもできますが、将来的な Scilab 6.0ではSOD形式のみがサポートされるとのことです。

SOD形式でファイルを保存する場合、以下のように変数名を""で括ります。

save("val.sod", "a", "b");

変数名を''で括らない場合は、従来のバイナリ形式で保存されます。5.3などの以前のバージョンとの互換性を維持する場合は、このように読み書きします。

save("val.dat", a, b);

XMLファイルアクセス関数の導入

XML形式のデータを読み書きする関数が導入されました。XML形式のファイルを読む場合に便利に使用できると思います。

課題

私のWindows環境では、グラフをクリップボード経由でコピーする機能が動かないようです。バグとして報告済みですので、次期バージョンでは修正されるものと期待します。

日本語化(メニューとヘルプ)は、私が細々と追加・更新しています。launchpadの翻訳システムで訳を作成しているため、具体的な画面表示と対比させた際に違和感がある場合があります。訳がおかしい場合など、個別にコメント頂ければ修正したいと思います。

2012-04-29

PHP 5.4.1リリースのポイント

PHP 5.4.1(及びPHP 5.3.11)が2012/4/27(日本時間)にリリースされました。リリースのポイントを以下にまとめます。

ファイルアップロード機能に関する脆弱性の修正(PHP 5.4.1/PHP 5.3.11で修正)

詳細は以下を参照ください:Fixed bug #54374 (Insufficient validating of upload name leading to corrupted $_FILES indices). (CVE-2012-1172)

以前から指摘されていたバグとのことですが、複数ファイルアップロード機能における変数パーサに余分な角括弧([,])の処理に関する不備があり、特殊な入力を行うことで、変数名($_FILES['foo']['name'])をContent-Typeで指定したMIME型で上書きされてしまうというものです。PHPの場合、Content-TypeのMIME型は、$_FILES['foo']['type']として取得可能で、MIME型の推定などに使用されますが、この部分はユーザ側で任意に書き換えることが可能であるため、ディレクトリトラバーサルなどの脆弱性が発生する可能性があります。

上記のURLで紹介される例を以下に紹介します。マルチパート形式のフォームで複数のファイルをアップロードされるシナリオです。

<form action="" method="POST" enctype="multipart/form-data" >
<input type="hidden" name="MAX_FILE_SIZE" value="10000000">
<input type="file" name="pictures[[type]">
<input type="file" name="pictures[[name]">
<input type="file" name="pictures[name][">
<input type="submit" value="submit">
</form>

通常のフォームと異なるのは、name属性に指定している変数名の括弧の数が対応していないことと、typeやnameといったPHP内部変数ハッシュキーと同一の属性を指定していることです。これらを指定することで、PHP変数パーサの不備をついていることになります。適当なWebブラウザでこのフォームを使ってアップロードを行うと、配列$_FILES['pictures']['name']の要素にapplicaion/octet-streamなどのファイルのMIME型が指定されてしまいます。

例えば、以下のようなコードを使用していた場合、ディレクトリトラバーサル脆弱性が発生します。

move_uploaded_file($_FILES['pictures']['tmp_name'][$key],
                                 $basedir . $_FILES['pictures']['name'][$key]);

ただし、このようなコード自体にはユーザの入力をそのまま使用するという大きな問題があり、より単純な攻撃を受ける可能性があります。ファイル名を直接指定させないホワイトリスト方式の採用やせめてbasename() 関数などでディレクトリトラバーサル攻撃を防ぐ仕組みが必要です。

ファイルアップロード機能のパーサは過去にも数回狙われており、近いところでは、 PHP 5.3.6までの脆弱性PHP 5.3.7で修正されています。

File path injection in PHP ≤ 5.3.6 file upload (CVE 2011-2202)

今回の指摘が問題視されたのは、過去の修正によりPHP側でnameキーについては不正な入力に関するチェックが入るようになっており、それに依存したアプリケーションコードを書いている場合に、typeキーについてはPHPで確認していないために、脆弱性をつかれる可能性があることだと思います。きちんとした脆弱性対策が講じられたアプリケーションでは発生し得ない問題だと思います。

Apache 2.4のサポート (PHP 5.4.1/PHP 5.3.11)

nginx対抗としてリリースされたApacheの最新版バージョン2.4に関して、一部の2.2との差異により、インストール時にエラーを発生するためにパッチが必要でしたが、このバージョンで修正されています。

マルチバイト文字対応コールバック型置換関数の導入(mbstring)

先日発売された弊著の「PHP徹底構築」にも記述していますが、mbstringエクステンションにmb_ereg_replace_callback()という関数PHP 5.4.1で追加されました。

この関数は、正規表現マッチングした文字列を置換するmb_ereg_replace()関数においてコールバック関数適用可能とするもので、preg_replace()に対するpreg_replace_callback()の関係に相当します。この種の機能は、従来、eオプションを使用してPHPコードを埋め込むことにより実装されるケースがありましたが、eオプションPHPコードインジェクションの脆弱性を発生する原因となるため、使用は推奨されておらず、preg_replace()においても将来の廃止の対象となっています。

簡単な使用例を以下に示します。

$str = 'abc 123 #';
echo mb_ereg_replace_callback('(\$+)', function($m) {
 return $m[1].'('.strlen($m[1]).')';
}, $str); // output: abc(3) 123(3) #",;(4) $foo(4)

この関数が普及した時点で、将来のPHPのバージョンでmb_ereg_replace()関数においてもeオプションに警告を出力することも考えられます。

domオブジェクトデバッグ情報強化

domを操作して、XMLデータを作成するアプリケーションを構築する際のデバッグに便利な機能です。例えば、以下のコードを見てみましょう。

<?php
$xml = <<<EOS
<foo>
 <bar>foobar</bar>
</foo>
EOS;
$dom = new domDocument;
$dom->dynamicProperty = new stdClass;
$dom->loadXML($xml);
print_r($dom);

PHP 5.4.0以前の出力は、以下となります。

DOMDocument Object
(
    [dynamicProperty] => stdClass Object
        (
        )

)

かなり、さみしいですね。

一方、PHP 5.4.1の場合は、以下のように詳細な情報が出力されます。

DOMDocument Object
(
    [dynamicProperty] => stdClass Object
        (
        )

    [doctype] => 
    [implementation] => (object value omitted)
    [documentElement] => (object value omitted)
    [actualEncoding] => 
    [encoding] => 
    [xmlEncoding] => 
    [standalone] => 1
    [xmlStandalone] => 1
    [version] => 1.0
    [xmlVersion] => 1.0
    [strictErrorChecking] => 1
    [documentURI] => /***/tests/
    [config] => 
    [formatOutput] => 
    [validateOnParse] => 
    [resolveExternals] => 
    [preserveWhiteSpace] => 1
    [recover] => 
    [substituteEntities] => 
    [nodeName] => #document
    [nodeValue] => 
    [nodeType] => 9
    [parentNode] => 
    [childNodes] => (object value omitted)
    [firstChild] => (object value omitted)
    [lastChild] => (object value omitted)
    [previousSibling] => 
    [attributes] => 
    [ownerDocument] => 
    [namespaceURI] => 
    [prefix] => 
    [localName] => 
    [baseURI] => /***/tests/
    [textContent] => 
 foobar

)