Bug(バグ) #2011
完了PHP 5.2.3〜5.2.5 で openpne:install をおこなうとセグメンテーション違反でインストールに失敗する
100%
説明
概要¶
PHP 5.2.3〜5.2.5 で openpne:install を実行すると、インストール開始時点でセグメンテーション違反となり、インストールできない。
>> installer start clean install セグメンテーション違反です
同梱されているセットアップドキュメントを確認すると、動作の想定バージョンはPHP5.2.3以降とある
OpenPNE3 は以下のようなサーバ環境で動作させることを想定しています。 Webサーバ Apache * mod_rewrite を使用可能 PHP PHP5.2.3 以降
note-19 で示されていますが、 PHP5.2.6 以降では、インストール時に問題は生じないようです。
確認バージョン¶
- stable-3.6.x ブランチ(beta8 以降で確認している)でかつ PHP5.2.3 - 5.2.5 の環境
OpenPNE-3.4.x では発生せず、 OpenPNE-3.7.0dev でも発生しない(特定の範囲のバージョンの ZendFramework で生じる問題で、それが OpenPNE-3.6.x である)。
詳細は note-20 を参照。
ファイル
Shingo Yamada さんが13年以上前に更新
- ステータス を New(新規) から Accepted(着手) に変更
- 担当者 を Naoya Tozuka から Shingo Yamada に変更
Shingo Yamada さんが13年以上前に更新
openpne:install を実行し SegmentationFault が発生するかどうかをPHPのバージョン毎に確認しました。
PHPのバージョン毎に確認結果¶
- php-5.2.3 NG
- php-5.2.4 NG
- php-5.2.5 NG
- php-5.2.6 OK
- php-5.2.8 OK
- php-5.2.17 OK
定義¶
- OK: SegmentationFault 発生せず
- NG: SegmentationFault 発生
「NG」状態の詳細¶
下記のタイミングで「Segmentation fault」が発生- 「/opt/phpall/bin/php-5.2.x symfony openpne:install」を実施(x ->バージョン)
- DB接続情報を入力
- (タスクが走り出す)
- 「installer start clean install」と表示
- 直後に「Segmentation fault」が表示され、処理がとまる
- 「Segmentation fault」発生時の表示
The Database Port Number : The Database Name : localhost The Database Socket : Is it OK to start this task? (Y/n) y >> installer start clean install Segmentation fault [shingo@csaXXX op36.shingo]$
Shingo Yamada さんが13年以上前に更新
http://openpne3.com/mediawiki/index.php?title=OpenPNE3%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6:SegmentationFault&oldid=462
上記に、以下の報告がありました。
OpenPNE3.6にバンドルされているZend_Http_Clientが原因。 lib/vendor/Zendをzend frameworkの最新版に置き換えると正常にコマンドを完了できる。
stable-3.6.x でも master と同様下記の操作を行い、最新の「zend framework」で 「Segmentation fault」が発生するかどうかを確認します。
commit 821abff4e86ab2fe50d592f5fe82209e14b653d7 Author: Kousuke Ebihara <ebihara@tejimaya.com> Date: Thu Sep 9 16:10:38 2010 +0900 updated bandled ZendFramework to latest stable release (ZendFramework 1.10.8) (fixes #205) I executed the following command: $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Acl $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Acl.php $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Exception $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Exception.php $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Feed $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Feed.php $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Http $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Http.php $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Loader $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Loader.php $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Mail $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Mail.php $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Mime $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Mime.php $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Registry $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Registry.php $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Search $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Search.php $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Uri $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Uri.php $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Validate $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Validate.php $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Version $ svn export http://framework.zend.com/svn/framework/standard/tags/release-1.10.8/library/Zend/Version.php
Maki Takahashi さんが13年以上前に更新
- ファイル Zend_Uri_Http.patch Zend_Uri_Http.patch を追加
- ステータス を Accepted(着手) から Pending Review(レビュー待ち) に変更
- 進捗率 を 0 から 50 に変更
#note-9 の通り、OpenPNE3.7.0(masterブランチ)ではZendFramework 1.10.8にバージョンアップされているため、解決済みですが
OpenPNE3.6(stable-3.6.xブランチ)に含まれるZendFramework 1.7.3PL1において
lib/vendor/Zend/ValidateHostname.php 358行目で落ちていることがわかりました。
// Check each domain part $status = @preg_match($regexLabel, $domainPart);
http://framework.zend.com/manual/ja/zend.validate.set.html#zend.validate.set.hostname.idn
国際化ドメイン名(IDN)を検証しないようにすれば、回避できます。
php5.2.5以降では、国際化ドメインを使用すると「Invalid URI supplied」という例外が発生するようになりますが
Punycode変換すれば上記の例外をさけることが可能です。
lib/vendor/Zend/Uri/Http.phpの446行目
$validate = new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_ALL);
↓
$validate = new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_ALL, false);
上記修正パッチを添付いたします。
Shingo Yamada さんが13年以上前に更新
- 対象バージョン を OpenPNE 3.7.0 から OpenPNE3.6beta13 に変更
master では起こらないため、本チケットの対象バージョンを 3.6 に変更します。
作成済みのBPチケットは閉じます。
Rimpei Ogawa さんが13年以上前に更新
- ステータス を Pending Review(レビュー待ち) から Rejected(差し戻し) に変更
Zend_Uri_Http を利用している箇所はインストール中に呼ばれるこの箇所だけではないため、「国際化ドメイン名(IDN)を検証しないようにする」という変更を安易にするべきではないと思います。
可能であれば、国際化ドメイン名の検証をした上で Segmentaion fault が発生しないような変更をした方がよいと思いますが、これは難しいでしょうか?
(こちらで少し確認したところ master ブランチ同梱の Zend_Uri_Http でも国際化ドメイン名の検証は行っているようなので不可能ではないと思いますが、Zend_Validate_Hostname がかなり変更されていたので容易ではないかもしれませんね...)
ただ、元々 symfony の sfValidatorUrl や _auto_link_urls() は国際化ドメイン名を考慮しない実装となっているため、これらの機構と一緒に Zend_Uri_Http を利用している箇所については、「国際化ドメイン名(IDN)を検証しないようにする」という変更は影響を受けないため、実際には問題ないケースがほとんどかもしれません。
Maki Takahashi さんが13年以上前に更新
- ステータス を Rejected(差し戻し) から Accepted(着手) に変更
masterに同梱されているZendFrameworkを参考にパッチを作り直します。
Maki Takahashi さんが13年以上前に更新
- ファイル Zend_Validate_Hostname.patch Zend_Validate_Hostname.patch を追加
- ステータス を Accepted(着手) から Pending Review(レビュー待ち) に変更
Zend_Validate_Hostname.phpを修正するパッチを作成し、「国際化ドメイン名の検証」を可能にしました。
が、しかし(これはMasterに同梱されているZendFrameworkでも発生するのですが)php5.2.4にて
Zend_Http_Clientに日本語ドメインを指定した場合、preg_matchでSegmentaion faultが発生するようですので
結果として?(日本語ドメインしか試していませんが)国際化ドメイン名の検証ができない状況のようです。
(ざっと調べただけですがpreg_matchの引数が長過ぎるとダメなようなので、うまい回避方法がなさそうに思われます)
(修正としては不十分に思われますが)
とりあえず、添付のパッチを適用した状態でphp5.2.4にてインストールが正常に動作することは確認済みです。
Rimpei Ogawa さんが13年以上前に更新
関連していると思われる情報メモ:
PHP 5.2.6 で PCRE のバージョンが上がっている。
Version 5.2.6
- Security Fixes
- Upgraded PCRE to version 7.6 (Nuno)
(※以下の表はChangeLogしか確認せずに作っています)
PHP | PCRE |
5.2.6 | 7.6 |
5.2.5 | 7.3 |
5.2.4 | 7.2 |
5.2.3 | 7.0 |
PCRE 7.6 の ChangeLog にそれらしい変更あり。
Version 7.6 28-Jan-08
codepoints greater than 255 (in UTF-8 mode, of course) caused a buffer1. A character class containing a very large number of characters with
overflow.
Rimpei Ogawa さんが13年以上前に更新
まず、こちらでの調査内容を書きます。(修正方針は次のコメントに分けます)
現在の master に同梱されている https://raw.github.com/openpne/OpenPNE3/master/lib/vendor/Zend/Validate/Hostname/Jp.php を読み込んで preg_match() に渡すだけのテストをしてみたところ、たしかに PHP 5.2.3〜5.2.5 では Segmentation fault が発生していました。
検証コード:
<?php $jp = include dirname(__FILE__).'/Jp.php'; echo '1 '; $pattern = $jp[1]; echo '2 '; preg_match($pattern, ''); echo 'Success'.PHP_EOL;
実行結果:
$ phpall test.php php-5.2.3: 1 2 php-5.2.4: 1 2 php-5.2.5: 1 2 php-5.2.6: 1 2 Success! php-5.2.8: 1 2 Success! php-5.2.9: 1 2 Success! php-5.2.10: 1 2 Success! php-5.2.11: 1 2 Success! php-5.2.12: 1 2 Success! php-5.2.13: 1 2 Success! php-5.2.14: 1 2 Success! php-5.2.15: 1 2 Success! php-5.2.16: 1 2 Success! php-5.2.17: 1 2 Success! php-5.3.0: 1 2 Success! php-5.3.1: 1 2 Success! php-5.3.2: 1 2 Success! php-5.3.3: 1 2 Success! php-5.3.4: 1 2 Success! php-5.3.5: 1 2 Success! php-5.3.6: 1 2 Success!
$ php-5.2.3 test.php 1 2 セグメンテーション違反です $ php-5.2.4 test.php 1 2 セグメンテーション違反です $ php-5.2.5 test.php 1 2 セグメンテーション違反です $ php-5.2.6 test.php 1 2 Success!
よって、Zend Framework 1.10.8 で問題が完全に解決されたわけではなく、master のコードでも国際化ドメイン名の検証が行われると 3.6 同様に Segmentation fault が発生するものと考えられます。
Zend Framework 1.10.8 で本チケットの問題が発生しなくなったのは、IDN検証用の正規表現によるマッチングの前に非IDNのドメイン名検証用の正規表現によるマッチングを行いこれが成功した場合にはIDN検証用の正規表現を利用しないコードに変更されたからです。そのため、以前のバージョンでは全URLに対して Segmentation fault が発生していたのに対し、新しいバージョンでは実際にIDNのURLを利用しようとしない限りは Segmentation fault が発生しなくなったものと思われます。
lib/vendor/Zend/Validate/Hostname.php
/** * Match against IDN hostnames * Note: Keep label regex short to avoid issues with long patterns when matching IDN hostnames * @see Zend_Validate_Hostname_Interface */ $regexChars = array(0 => '/^[a-z0-9\x2d]{1,63}$/i'); if ($this->_options['idn'] && isset($this->_validIdns[strtoupper($this->_tld)])) { if (is_string($this->_validIdns[strtoupper($this->_tld)])) { $regexChars += include($this->_validIdns[strtoupper($this->_tld)]); } else { $regexChars += $this->_validIdns[strtoupper($this->_tld)]; } } ... // Check each domain part $checked = false; foreach($regexChars as $regexKey => $regexChar) { $status = @preg_match($regexChar, $domainPart); if ($status > 0) { ... $checked = true; break; ... } }
Rimpei Ogawa さんが13年以上前に更新
- ステータス を Pending Review(レビュー待ち) から Rejected(差し戻し) に変更
問題点について整理¶
PHP 5.2.3〜5.2.5(本チケットのタイトルは 5.2.5 が抜けている)の環境で、
- openpne:install をおこなうとセグメンテーション違反でインストールに失敗する
- Zend_Validate_Hostname を利用するクラス(例えば、Zend_Http_Client)で、特定のドメイン名(※)を含む URL を利用した場合にセグメンテーション違反が発生する
- (※)国際化ドメイン名を許容し、Zend_Validate_Hostname で用意されている検証用の正規表現が長いもの。例えば、.jp
- 標準設定では、openpne:install 時に Zend_Http_Client に plugins.openpne.jp を含む URL を渡すために問題が発生する
- OpenPNE対象ブランチ
- master ブランチでは発生しない
- stable-3.6.x ブランチでは発生する
- stable-3.4.x ブランチではおそらく発生しない(.jp の国際化ドメインに Zend_Validate_Hostname が対応していないため)
- Zend_Validate_Hostname を利用するクラス(例えば、Zend_Http_Client)で、特定のドメイン名(※)を含む URL を利用した場合にセグメンテーション違反が発生する
- (具体的な問題は報告されていないが)国際化ドメイン名を含む URL を利用しようとするとセグメンテーション違反が発生する可能性がある
- Zend_Validate_Hostname を利用するクラス(例えば、Zend_Http_Client)で、特定のドメイン名(※)の 国際化ドメイン名を含む URL を利用した場合にセグメンテーション違反が発生する
- (※)国際化ドメイン名を許容し、Zend_Validate_Hostname で用意されている検証用の正規表現が長いもの。例えば、.jp
- 例えば、
plugins.openpne.jp
は問題なく、日本語.jp
は問題がある
- OpenPNE対象ブランチ
- master ブランチで発生する
- stable-3.6.x ブランチで発生する
- stable-3.4.x ブランチでも発生すると思われるが、対象のドメイン名は master や 3.6 のものとは異なる(.jp は未対応。また、他のドメインに関してもなぜか正規表現が短いものが多いので発生しないかもしれない)
- Zend_Validate_Hostname を利用するクラス(例えば、Zend_Http_Client)で、特定のドメイン名(※)の 国際化ドメイン名を含む URL を利用した場合にセグメンテーション違反が発生する
修正方針についての提案¶
まず、本チケットにおいては 問題1 の openpne:install 時にセグメンテーション違反が発生する問題についてのみ対象とし、問題2 については別チケット扱いとするのがよいと思います。(問題2 については具体的な問題が報告されておらず、国際化ドメイン名が利用されて問題の発生する可能性のある箇所も非常に限られているため、緊急性はないと考えられる)
その上で本チケットの修正内容としては、note-12 のパッチをベースとし、PHPのバージョンを確認し 5.2.6 未満の場合のみ国際化ドメイン名の検証を行わないようにする分岐を追加する方法を提案します。(バージョンの比較には PHP の version_compare() 関数 が使えます)
PHP 5.2.6 以上の環境についてはこれまで通り動作し、PHP 5.2.6 未満の環境においては元々セグメンテーション違反により国際化ドメイン名が利用できない状態であったので、この変更により現状より悪くなることはありません。
また、 note-17 のパッチに比べると小さい変更で済むため、安定版リリース前にも適用しやすいというメリットもあります。
Maki Takahashi さんが13年以上前に更新
- 題名 を php5.2.3・php5.2.4 で openpne:install をおこなうとセグメンテーション違反でインストールに失敗する から PHP 5.2.3〜5.2.5 で openpne:install をおこなうとセグメンテーション違反でインストールに失敗する に変更
- 説明 を更新 (差分)
- ステータス を Accepted(着手) から Pending Review(レビュー待ち) に変更
Kousuke Ebihara さんが13年以上前に更新
- ステータス を Pending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
- 進捗率 を 50 から 70 に変更
Mutsumi Imamura さんが13年以上前に更新
下記のPHPバージョン下でインストールタスクを実行し、実行直後にセグメンテーション違反が発生しないことを確認しました。
- PHP5.2.3
- PHP5.2.4
- PHP5.2.5
- PHP5.2.6
- PHP5.2.8
- PHP5.2.17
テスト実施時に1点気になった点は、PHP5.2.17でインストールタスクを実行したところ、スキーマを読み込む直後くらいにセグメンテーション違反が発生しました。
しかし、再度実行したところ再現せず問題なくインストールすることが出来ました。
このチケットで問題視されていたインストール直後にセグメンテーション違反が発生することとはまた別の問題であると考えられることと、100%再現するというわけではないのでこのチケットは修正完了とします。
別途、チケットを作成し対応するのが望ましいかと思います。
下記はセグメンテーション違反発生時のターミナル出力の一部抜粋です。
>> file+ /home/tetete/sns/php-5.2.17.tetete.jp/data/fixtures_tmp/012_000_revision_51da175b32839d5dc41ab76d63dab10c.yml >> file+ /home/tetete/sns/php-5.2.17.tetete.jp/data/fixtures_tmp/012_010_navigation_0d7169e208ca9d16a84085575c34d1b9.yml >> file+ /home/tetete/sns/php-5.2.17.tetete.jp/data/fixtures_tmp/012_020_gadget_854d0f4d0df31fd028b4c8e75a0a6096.yml >> doctrine Dropping "doctrine" database >> doctrine SQLSTATE[HY000]: General error: 1008 Can't drop database 'tetete'; database doesn't exist. Failing Query: "DROP DATABASE tetete" >> doctrine Creating "prod" environment "doctrine" database >> doctrine generating model classes >> file+ /tmp/doctrine_schema_48626.yml Segmentation fault
Mutsumi Imamura さんが13年以上前に更新
- ステータス を Pending Testing(テスト待ち) から Fixed(完了) に変更
- 進捗率 を 70 から 100 に変更
テスト実施時に1点気になった点は、PHP5.2.17でインストールタスクを実行したところ、スキーマを読み込む直後くらいにセグメンテーション違反が発生しました。
については↓のチケットで対応することにしましょう。
php-5.2.17の環境でインストールタスクを実行するとセグメンテーション違反が発生する場合がある
http://redmine.openpne.jp/issues/2357