Skip to content

Instantly share code, notes, and snippets.

@upsilon
Created April 18, 2016 07:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save upsilon/5e456b216ced39af2a298f4984102c8f to your computer and use it in GitHub Desktop.
Save upsilon/5e456b216ced39af2a298f4984102c8f to your computer and use it in GitHub Desktop.
redmine.openpne.jp に報告しようとしたらRedmineのエラーで送信できなかった内容

題名: Zend_Validate_Hostnameクラスで .com, .biz, .cn ドメインのホスト名がエラーになる

説明:

h3. Overview (現象)

Zend_Validate_Hostname を使用する機能で .com, .biz, .cn ドメインのホスト名または URL がエラーになる。

具体的には、下記の機能で問題が発生する。

 * OpenPNE.yml の @mail_smtp_host@
 ** 例: @smtp.gmail.com@ を使用したメール送信が行えない<pre><code class="yaml">
mail_smtp_host: "smtp.gmail.com"
mail_smtp_config:
  auth:     "login"
  username: "*****@gmail.com"
  password: “*****”
  ssl:      "tls"
  port:     587 
</code></pre>
 ** 発生するエラーの例: {{collapse(詳細を表示...)
<pre>
$ ./symfony openpne:send-daily-news --app=pc_frontend --trace

                                         
  [Zend_Validate_Exception]              
  Internal error: DNS validation failed  
                                         

Exception trace:
  at /home/upsilon/git/openpne3/v3.6/lib/vendor/Zend/Validate/Hostname.php:365
 Zend_Validate_Hostname->isValid at /home/upsilon/git/openpne3/v3.6/lib/vendor/Zend/Validate.php:94
 Zend_Validate->isValid at /home/upsilon/git/openpne3/v3.6/lib/vendor/Zend/Mail/Protocol/Abstract.php:133
 Zend_Mail_Protocol_Abstract->__construct at /home/upsilon/git/openpne3/v3.6/lib/vendor/Zend/Mail/Protocol/Smtp.php:156
 Zend_Mail_Protocol_Smtp->__construct at /home/upsilon/git/openpne3/v3.6/lib/vendor/Zend/Mail/Protocol/Smtp/Auth/Login.php:76
 Zend_Mail_Protocol_Smtp_Auth_Login->__construct at /home/upsilon/git/openpne3/v3.6/lib/vendor/Zend/Mail/Transport/Smtp.php:196
 Zend_Mail_Transport_Smtp->_sendMail at /home/upsilon/git/openpne3/v3.6/lib/vendor/Zend/Mail/Transport/Abstract.php:348
 Zend_Mail_Transport_Abstract->send at /home/upsilon/git/openpne3/v3.6/lib/vendor/Zend/Mail.php:936
 Zend_Mail->send at /home/upsilon/git/openpne3/v3.6/lib/util/opMailSend.class.php:218
 opMailSend::execute at /home/upsilon/git/openpne3/v3.6/lib/util/opMailSend.class.php:156
 opMailSend::sendTemplateMail at /home/upsilon/git/openpne3/v3.6/lib/task/openpneSendDailyNewsTask.class.php:112
 openpneSendDailyNewsTask->sendDailyNews at /home/upsilon/git/openpne3/v3.6/lib/task/openpneSendDailyNewsTask.class.php:43
 openpneSendDailyNewsTask->execute at /home/upsilon/git/openpne3/v3.6/lib/vendor/symfony/lib/task/sfBaseTask.class.php:68
 sfBaseTask->doRun at /home/upsilon/git/openpne3/v3.6/lib/vendor/symfony/lib/task/sfTask.class.php:97
 sfTask->runFromCLI at /home/upsilon/git/openpne3/v3.6/lib/vendor/symfony/lib/command/sfSymfonyCommandApplication.class.php:76
 sfSymfonyCommandApplication->run at /home/upsilon/git/openpne3/v3.6/lib/vendor/symfony/lib/command/cli.php:20
 include at /home/upsilon/git/openpne3/v3.6/symfony:14
</pre>
}}
 * opOpenSocialPlugin のアプリ追加
 ** 例: 管理画面の「アプリ追加」(/pc_backend_dev.php/opOpenSocialPlugin/add) で @Gadget XML URL@ に @gist.github.com@ などのドメインの URL を指定するとエラーになる

この不具合は OpenPNE *3.4.x* および *3.6.x* のみで発生する。

h3. Causes (原因)

#205 で起きた問題の修正のために、@Zend_Validate_Hostname@ に対して @3.7.0@ 以降とそれ以前で異なる修正が行われた。
この修正により OpenPNE 3.6.x には commit:fbdbb216 の修正が行われたが、「最新の安定版で配布されている Zend/Validate/Hostname/*.php とほぼ近い挙動になるようなクラスファイル」が正しく機能しなかったため今回の不具合が起きた。

#205-6 より引用:
> 次の方針で実装します。
> 
>  * OpenPNE 3.7.0    : 同梱する ZendFramework の最新の安定版にアップデートします
>  * OpenPNE 3.6 以前 : ZendFramework の最新の安定版に存在する Zend/Validate/Hostname/*.php に対応するファイルが同梱している ZendFramework に存在していなければ、最新の安定版で配布されている Zend/Validate/Hostname/*.php とほぼ近い挙動になるようなクラスファイルを追加するという暫定的な対処をおこないます

h4. *.biz, *.cn ドメインの場合に発生するエラー

<pre>
PHP Warning:  preg_match(): Compilation failed: regular expression is too large at offset 156194 in /home/upsilon/git/openpne3/v3.6/lib/vendor/Zend/Validate/Hostname.php on line 358
</pre>

source:lib/vendor/Zend/Validate/Hostname/Biz.php@fbdbb216 のパターンは 207,460 文字、 source:lib/vendor/Zend/Validate/Hostname/Cn.php@fbdbb216 のパターンは 156,176 文字と非常に巨大な正規表現パターンとなっており、このことがエラーの原因であると考えられる。

3.7.0 以降に対して修正された source:lib/vendor/Zend/Validate/Hostname/Biz.php@821abff4 は複数に分割された正規表現パターンを使用してドメイン名をチェックしているため今回のような問題は発生していない。

h4. *.com ドメインの場合に発生するエラー

<pre>
PHP Warning:  preg_match(): Compilation failed: disallowed Unicode code point (>= 0xd800 && <= 0xdfff) at offset 9800 in /home/upsilon/git/openpne3/v3.6/lib/vendor/Zend/Validate/Hostname.php on line 358
</pre>

コードポイント U+D800 から U+DFFF までの範囲は Unicode のサロゲートペアの high surrogates および low surrogates のために確保された領域であり、これらの領域では 2 つの符号単位で 1 文字として扱うためいずれか単体で正規表現パターンにマッチすることはない。
例えば「🍣」という文字は U+D83C U+DF63 の組で 1 文字として扱われるため @/\x{D800}-\x{DFFF}/u@ のような正規表現パターンを用いてもマッチすることはない(サロゲートペアは U+10000 以降のコードポイントで表され、「🍣」は U+1F363 であるため @/\x{1F363}/u@ であればマッチする)

<pre>
$ echo -n '🍣' | nkf -W -w16B0 | xxd
00000000: d83c df63                                .<.c
$ php -r "var_dump(preg_match('/\x{D800}-\x{DFFF}/u', '🍣'));"
PHP Warning:  preg_match(): Compilation failed: disallowed Unicode code point (>= 0xd800 && <= 0xdfff) at offset 7 in Command line code on line 1

Warning: preg_match(): Compilation failed: disallowed Unicode code point (>= 0xd800 && <= 0xdfff) at offset 7 in Command line code on line 1
bool(false)
$ php -r "var_dump(preg_match('/\x{1F363}/u', '🍣'));" 
int(1)
</pre>

source:lib/vendor/Zend/Validate/Hostname/Com.php@fbdbb216 の正規表現パターンには @\x{D800}-\x{DB7F}\x{DC00}-\x{DFFF}@ が含まれており、この部分がサロゲートペアの領域に該当するため上記のエラーが発生したと考えられる。
実際にこの部分を除去すると *.com ドメインのホスト名でエラーになる現象は起きなくなった。

h3. Way to fix (修正内容)

修正内容を記入
@upsilon
Copy link
Author

upsilon commented Apr 18, 2016

たぶん寿司のせい

@upsilon
Copy link
Author

upsilon commented Apr 18, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment