がるの健忘録

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

またバグ;;

えっと………ええタイトルの通りですともさ。…泣くぞ。
以下、まだ分析はしきれていないのですが、状況を簡単に。

直接的な事象
・とあるプログラムにおいて、ob_cleanを事前に発行した際に画像が壊れる
・対象プログラムにおいてはob_clean行をコメントアウトすることで現象を回避できることが判明

事象に対する事実
・簡単なテストプログラムを作成、実施(約10ステップ)。テストプログラムにおいてはob_cleanによる弊害は発生せず。
・ob_clean及びob_startを含む、ob_*のソースコード(5.1.2、4.4.2、4.3.11)を確認。
 概ね、キャッシュ実現のための「フラグのon/off、バッファ領域の確保/破棄」およびそれに伴うlockなどがメインで、関数深度3以内においてそれ以上の処理は特になし。

資料
以下、正常及び異常状態の出力データdump

正常
0000000 5089 474e 0a0d 0d1a 000a 0000 490d 4448
0000020 0052 0000 0064 0000 0164 0003 0000 2c4a
0000040 1707 0000 0600 4c50 4554 0000 0000 221b
0000060 0000 9300 4449 5441 8d38 cfed 0db1 4103
0000100 4408 05d1 1011 0252 1c9d d1a5 6db9 77c9
0000120 fcd2 1c0e 9278 23d5 81d8 7e73 ab32 c830
0000140 80a1 2a12 a1a8 5681 6865 2877 84a0 0a0d
0000160 686a 55a0 ae19 2875 84a0 0a0d 686a 55a0
0000200 51d9 1439 4250 3505 d034 ecaa 1ca8 0a0d
0000220 a128 1a82 681a 7655 0e54 9405 4150 0d0d
0000240 2ab4 d9d3 f75d a028 0d84 6a0a 2068 863c
0000260 1c1d 0a0d a128 1a82 681a 4f55 57dd 050e
0000300 5094 d741 ceeb f7f3 9f3f 01bc 49fb cf33
0000320 6a6f 5bc9 0000 0000 4549 444e 42ae 8260
0000340 000a

異常
0000000 503f 474e 0a0d 0d1a 000a 0000 490d 4448
0000020 0052 0000 0064 0000 0164 0003 0000 2c4a
0000040 1707 0000 0600 4c50 4554 0000 3f00 0000
0000060 3f1b 223f 0000 3f00 4449 5441 3f38 6ee7
0000100 030d 0841 0544 1011 0252 1c3f 7083 3f3f
0000120 fa99 1c0e 3f78 3f3f 7e73 3f32 9f94 123f
0000140 842a 3f9f 6556 7768 3f28 0d3f 6a0a 3f68
0000160 1955 283f 3f3f 0a0d 686a 553f 393f 5014
0000200 0542 3435 a898 a6e6 0d1c 280a 1a3f 681a
0000220 7655 0e54 3f05 4150 0d0d 9a3f 5d78 3f3f
0000240 0d3f 6a0a 2068 3f3c 1c1d 0a0d 3f28 1a1a
0000260 5568 3f4f 050e 503f 9c41 978b 3ff1 013f
0000300 333f 6a3f 003f 0000 4900 4e45 3f44 3f60
0000320 000a

上述からの考察
直近のポイントは1byte目上位4bit(Linuxはリトルエンディアンなので上位bitが下にくる)。
正しくは0x89であるべきところが0x3fになっている。そう考えて異常データを見ると、0x3fがむやみに散らかっていることがわかる。
ASCIIコードにおいて、0x89は割り当てがなされておらず(かつ上位ビットが立っている点にも留意)、一方で0x3fは?に割り当てられている。
データ異常の引き金が最上位ビットに関連している(いうまでもなくこれはeucもしくはshift-jisの特徴)、日本語変換処理において「不明なコード」時によく割り当てられている?(0x3f)が頻出するあたりから、PHPが孕む「バッファデータの自動的な文字置換にからむバグ」である可能性が推測される。
もうちょっと突っ込むと、高い確率で「日本語ローカル処理周りが(恐らくは勝手に)どこかのタイミングでキャッシュに対してコード変更を自動で行ってしまっている」であろうことが予見される。

結論
通常の文字列についてはよいのだが、いわゆるバイナリ系のデータを扱う場合(直近には暗号データなど)は、不明な不具合が起きたときにこの可能性を考慮する必要があると思われる。
なお、実際にデータが置換されてしまっているタイミングが不明であるために、変数格納データについて「安全である」保証はない。

……どないせいと;;