Project

General

Profile

Bug(バグ) #2011

PHP 5.2.3〜5.2.5 で openpne:install をおこなうとセグメンテーション違反でインストールに失敗する

Added by Kiwa Sakai over 8 years ago. Updated about 8 years ago.

Status:
Fixed(完了)
Priority:
High(高め)
Target version:
Start date:
2011-04-21
Due date:
% Done:

100%

3.6 で発生するか:
Yes
3.8 で発生するか:
Unknown (未調査)

Description

概要

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 を参照。

Zend_Uri_Http.patch View (543 Bytes) Maki Takahashi, 2011-07-27 15:35

Zend_Validate_Hostname.patch View (911 KB) Maki Takahashi, 2011-08-05 23:29


Related issues

Related to OpenPNE 3 - Backport(バックポート) #2201: php5.2.3・php5.2.4 で openpne:install をおこなうとセグメンテーション違反でインストールに失敗する Invalid(無効) 2011-06-10
Related to OpenPNE 3 - Bug(バグ) #2349: PHP 5.2.3〜5.2.5で国際化ドメイン名を含む URL を利用しようとするとセグメンテーション違反が発生する可能性がある New(新規) 2011-08-13

Associated revisions

Revision 70ef9ba5 (diff)
Added by Maki Takahashi about 8 years ago

(refs #2011) added "IDN domains are not validated" option of Zend_Validate_Hostname if PHP_VERSION < 5.2.6 in openpne:install

History

#1 Updated by Kiwa Sakai over 8 years ago

環境の問題かもしれないため確認が必要なので、OpenPNE3.6のバックポートは作成していません。

#2 Updated by Shingo Yamada over 8 years ago

  • Priority changed from Normal(通常) to High(高め)

#3 Updated by Shingo Yamada over 8 years ago

  • 3.6 で発生するか set to Yes

#4 Updated by Shingo Yamada over 8 years ago

sakaiさんに本件の発生環境を依頼済みです。(amazonEC2, ~5/25)

#5 Updated by Minoru Takai over 8 years ago

  • Target version set to OpenPNE 3.7.0

#6 Updated by Shingo Yamada over 8 years ago

  • Assignee set to Naoya Tozuka

#7 Updated by Shingo Yamada about 8 years ago

  • Status changed from New(新規) to Accepted(着手)
  • Assignee changed from Naoya Tozuka to Shingo Yamada

#8 Updated by Shingo Yamada about 8 years ago

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]$ 
    

#9 Updated by Shingo Yamada about 8 years ago

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

#10 Updated by Shingo Yamada about 8 years ago

検証結果

#note-9 の内容を実施する前後で動作確認を行った。

before
  • stable-3.6.x / php-5.2.3 : NG
  • stable-3.6.x / php-5.2.6 : OK
after
  • stable-3.6.x / php-5.2.3 : OK
  • stable-3.6.x / php-5.2.6 : OK

上記の結果より、本チケットは ZendFramework 1.10.8 にバージョンアップすることで解決できる問題であるといえる。

#11 Updated by Shingo Yamada about 8 years ago

  • Assignee changed from Shingo Yamada to Maki Takahashi

#12 Updated by Maki Takahashi about 8 years ago

  • File Zend_Uri_Http.patch View added
  • Status changed from Accepted(着手) to Pending Review(レビュー待ち)
  • % Done changed from 0 to 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);

上記修正パッチを添付いたします。

#13 Updated by Shingo Yamada about 8 years ago

  • Target version changed from OpenPNE 3.7.0 to OpenPNE3.6beta13

master では起こらないため、本チケットの対象バージョンを 3.6 に変更します。
作成済みのBPチケットは閉じます。

#14 Updated by Rimpei Ogawa about 8 years ago

  • Status changed from Pending Review(レビュー待ち) to Rejected(差し戻し)

Zend_Uri_Http を利用している箇所はインストール中に呼ばれるこの箇所だけではないため、「国際化ドメイン名(IDN)を検証しないようにする」という変更を安易にするべきではないと思います。

可能であれば、国際化ドメイン名の検証をした上で Segmentaion fault が発生しないような変更をした方がよいと思いますが、これは難しいでしょうか?
(こちらで少し確認したところ master ブランチ同梱の Zend_Uri_Http でも国際化ドメイン名の検証は行っているようなので不可能ではないと思いますが、Zend_Validate_Hostname がかなり変更されていたので容易ではないかもしれませんね...)

ただ、元々 symfony の sfValidatorUrl や _auto_link_urls() は国際化ドメイン名を考慮しない実装となっているため、これらの機構と一緒に Zend_Uri_Http を利用している箇所については、「国際化ドメイン名(IDN)を検証しないようにする」という変更は影響を受けないため、実際には問題ないケースがほとんどかもしれません。

#15 Updated by Maki Takahashi about 8 years ago

  • Status changed from Rejected(差し戻し) to Accepted(着手)

masterに同梱されているZendFrameworkを参考にパッチを作り直します。

#16 Updated by Shingo Yamada about 8 years ago

  • 360対象 set to beta13

#17 Updated by Maki Takahashi about 8 years ago

Zend_Validate_Hostname.phpを修正するパッチを作成し、「国際化ドメイン名の検証」を可能にしました。

が、しかし(これはMasterに同梱されているZendFrameworkでも発生するのですが)php5.2.4にて
Zend_Http_Clientに日本語ドメインを指定した場合、preg_matchでSegmentaion faultが発生するようですので
結果として?(日本語ドメインしか試していませんが)国際化ドメイン名の検証ができない状況のようです。
(ざっと調べただけですがpreg_matchの引数が長過ぎるとダメなようなので、うまい回避方法がなさそうに思われます)

(修正としては不十分に思われますが)
とりあえず、添付のパッチを適用した状態でphp5.2.4にてインストールが正常に動作することは確認済みです。

#18 Updated by Rimpei Ogawa about 8 years ago

関連していると思われる情報メモ:

PHP 5.2.6 で PCRE のバージョンが上がっている。

Version 5.2.6

  • Security Fixes
    • Upgraded PCRE to version 7.6 (Nuno)

http://php.net/ChangeLog-5.php#5.2.6

(※以下の表は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


1. A character class containing a very large number of characters with

codepoints greater than 255 (in UTF-8 mode, of course) caused a buffer
overflow.

http://www.pcre.org/changelog.txt

#19 Updated by Rimpei Ogawa about 8 years ago

まず、こちらでの調査内容を書きます。(修正方針は次のコメントに分けます)

現在の 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;
        ...
    }
}

#20 Updated by Rimpei Ogawa about 8 years ago

  • Status changed from Pending Review(レビュー待ち) to Rejected(差し戻し)

問題点について整理

PHP 5.2.3〜5.2.5(本チケットのタイトルは 5.2.5 が抜けている)の環境で、

  1. 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 が対応していないため)
  2. (具体的な問題は報告されていないが)国際化ドメイン名を含む 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 は未対応。また、他のドメインに関してもなぜか正規表現が短いものが多いので発生しないかもしれない)

修正方針についての提案

まず、本チケットにおいては 問題1 の openpne:install 時にセグメンテーション違反が発生する問題についてのみ対象とし、問題2 については別チケット扱いとするのがよいと思います。(問題2 については具体的な問題が報告されておらず、国際化ドメイン名が利用されて問題の発生する可能性のある箇所も非常に限られているため、緊急性はないと考えられる)

その上で本チケットの修正内容としては、note-12 のパッチをベースとし、PHPのバージョンを確認し 5.2.6 未満の場合のみ国際化ドメイン名の検証を行わないようにする分岐を追加する方法を提案します。(バージョンの比較には PHP の version_compare() 関数 が使えます)

PHP 5.2.6 以上の環境についてはこれまで通り動作し、PHP 5.2.6 未満の環境においては元々セグメンテーション違反により国際化ドメイン名が利用できない状態であったので、この変更により現状より悪くなることはありません。

また、 note-17 のパッチに比べると小さい変更で済むため、安定版リリース前にも適用しやすいというメリットもあります。

#21 Updated by Maki Takahashi about 8 years ago

  • Status changed from Rejected(差し戻し) to Accepted(着手)

#22 Updated by Maki Takahashi about 8 years ago

  • Subject changed from php5.2.3・php5.2.4 で openpne:install をおこなうとセグメンテーション違反でインストールに失敗する to PHP 5.2.3〜5.2.5 で openpne:install をおこなうとセグメンテーション違反でインストールに失敗する
  • Description updated (diff)
  • Status changed from Accepted(着手) to Pending Review(レビュー待ち)

70ef9ba5 にて

note-12 のパッチをベースとし、PHPのバージョンを確認し 5.2.6 未満の場合のみ国際化ドメイン名の検証を行わないようにする分岐を追加する方法

を採用しました。

php5.2.4の環境および、php5.3.2の環境両方にてインストールが正常に行えることを確認いたしました。

問題2については、別途チケットを作成しました( #2349

#23 Updated by Minoru Takai about 8 years ago

  • Description updated (diff)

チケットの Description の一部が古かったので修正

#24 Updated by Kousuke Ebihara about 8 years ago

  • Status changed from Pending Review(レビュー待ち) to Pending Testing(テスト待ち)
  • % Done changed from 50 to 70

#25 Updated by Mutsumi Imamura about 8 years ago

下記の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

#26 Updated by Mutsumi Imamura about 8 years ago

  • Status changed from Pending Testing(テスト待ち) to Fixed(完了)
  • % Done changed from 70 to 100

テスト実施時に1点気になった点は、PHP5.2.17でインストールタスクを実行したところ、スキーマを読み込む直後くらいにセグメンテーション違反が発生しました。

については↓のチケットで対応することにしましょう。

php-5.2.17の環境でインストールタスクを実行するとセグメンテーション違反が発生する場合がある
http://redmine.openpne.jp/issues/2357

Also available in: Atom PDF