こんばんは森川です。先日すべてShift_JISで書かれているおかしな環境で変な挙動をPHPがしたので少し調べてみた(おかしな環境で変な挙動も当然かもしれないけど)。
結局バグなのかどうかはわからないが(本来サポートされてないShift_JISで起きてるし)、とりあえずSegmentation faultとかzend_mm_heap corruptedとかまで起きたのでバグ報告だけは簡単にしておいた。詳しい内容は以下の通りです。
まずは、基本的なおさらい。PHPのマルチバイトのconfigureオプションには--with-mbstringと--enable-zend-multibyteがあります。
--with-mbstring
mbstring関数を使用するためのオプション(大抵の場合このオプションは有効なはず)
--enable-zend-multibyte
Zend Engine内でマルチバイト処理を行うためのオプション(あまり使われていない?)
ちなみに、zend-multibyteが有効になっていないと、Shift_JISで記述されたファイルでParse Errorが発生することがあります(当然といえば当然なのだが)。例えば以下のようなファイルがShift_JISで記述されていたとしましょう。
<?php
echo '可能';
?>
「能」という文字はShift_JISでは「945C」というバイナリであり、「5C」というバイナリは「\」となっているので、echo "xxxxx\"; を実行しようとしているのだ!とZend Engineは考え、Parse Errorが起きるわけです。
そして、zend-multibyteが有効になっていると、「能」をマルチバイトと認識することが可能となります。この機能を使用している人がどれほどいるかは謎ですが、このShift_JISを使用するのが結構問題です。
どんな問題が発生するかというと、PHPファイルでPHPタグがないファイルを実行しても文字化けもしくはSegmentation faultを起こすのです。ちなみにかなりのレアケースなので、この問題にあたる人はそんなにいないでしょう。
かなりがんばって作り上げた文字化けするファイルの内容は以下の通りです。[ダウンロード]
<html>
<head>
<title>test</title>
</head>
<body>
あいうえおかきくけこ
ファフィフェフェフォニャニィニュニェニョ
asdfasdfasdfsdfjalsdkfja;sldfja;lsdkjf
sdfasdf
ピャピィピュピェピョ
hogehoge hogehoge aaa
○○○ホゲホゲーuーー イイ
「「「「「「「「ーーーーー「「「「ー「ー「ー「ー「ー「ー「ー「
アイウエオーカキクケコーサシスセソー★
ァィゥェォガギグゲゴザジズゼゾダヂヅデドバビブベボ「パピプペポ」ナニヌネノhogehoge
</body></html>
これを適当なPHPファイルとしてリネームします。改行・スペース一つ違うだけで文字化けしたりしなかったりなので結構注意が必要です。出力される内容は以下のようになります。script_encodingをShift_JISもしくはSJIS-winにしておくことを忘れずに。
あいうえおかきくけこファフィフェフェフォニャニィニュニェニョ asdfasdfasdfsdfjalsdkfja;sldfja;lsdkjf sdfasdf ピャピィピュピェピョ hogehoge hogehoge aaa ○○○ホゲホゲーuーー イイイ ウ「「「「「「「「ーーーーー「「「「ー「ー「ー「ー「ー「ー「ー「アイウエオーカキクケコーサシスセソー★ ァィゥェォガギグゲゴザジズゼゾダ・沍糟沍・沍柱沍阜沍・沍膜沍・沍洛沍′阜・・・膜・・・洛・・・東・伯譜ogehoge
そして上記のファイルのasdfasdfasdfasdf..... という行を削除して実行するとSegmentation Faultで落ちます。他にもzend_mm_heap corruptedなどのメッセージも出てきました。バイナリファイルを実行しているようなものだけど、使用しているものはJIS第一水準だと思うので、できたら修正して欲しいところです。
ちなみに、自分は script_encoding は使用していません。設定がある場合でも UTF-8 にしておきます。なんだかんだといって、UTF-8が一番よいです。
これを機に少し勉強しようと思って zend_multibyte.c とか mbstring.c なんかを少し眺めていたのですが、よくわからなかった。。ということでGWにちゃんと見て理解しよう!と宣言しておけばきっとやるはず。。。