蝉は、やがて死ぬる午後に気づいた。ああ、私たち、もっと仕合せになってよかったのだ。:2014年06月12日分

2014/06/12(Thu)

[自宅システム管理者][Multimedia][Photoshop] Photomergeプラグインに於いて、レイアウトを「手動設定」で画像結合するとPhotoshopがクラッシュする

以前のどーでもいい記事 Windows XP の EOL 対応 Photoshop Elements 5 が Windows 7 未対応だったので、ワイのジャンク箱にあった 同 8のライセンスを譲ったちゅー話を書きましたが、しばらく運用した結果エンドユーザー様から「使えない」と自宅システム管理者に苦情が来たのでそのネタでも。

@Photomerge プラグインとは?

最近(といってもだいぶ前からだな)の Photoshop Elements および Creative Suite には Photomerge というプラグインがあって、複数毎の写真を繋げてパノラマ写真を作成するのを自動でやってくれたりします *1。要はそれぞれの画像同士 diff とって同じ部分を重ねてひとつの画像にするバッチ処理です。

ただし差分判定しにくい写真は所詮機械なので結合に失敗するので、その場合ユーザさんサイドがマウスでグリグリっと結合するモードもあります。 内部的には Photomerge プラグインから更に別の PhotomergeUI プラグインが呼び出されるという動作になっとるようです。

@落ちたな(確信)

ところがこの PhotomergeUI プラグインが起動すると Photoshop のウインドウタイトルが「(応答なし)」になり

Adone Photoshop CS6 は動作を停止しました

問題の解決をオンラインで確認できます。(確認できるとはいっていない)

→ オンラインで解決策を確認してプログラムを終了します(解決策があるとはいっていない)
→ プログラムを終了します m9(^Д^)プギャー

というダイアログが出て本体ごと落っこちる模様、だいじっこ!

@本家 Adobe による素晴らしい対応

本家 Adobe のフォーラムにも Photomerge プラグインが応答なしになる現象について報告があり、原因についても

  • メモリだ、メモリを増設するんだ! (富豪プログラミングはバグの元だよ派)
  • それもECCメモリだ! (宇宙線が全てのバグの原因だよ派)
  • グラボドライバとの相性問題だ、環境設定のパフォーマンスでキャッシュレベルを変更すると改善する! (ハード最適化パフォ厨プログラミングはバグの元だよ派)
  • 最新版にすれば直ってるかもしれない (お布施、とにかくお布施が重要だよカッキーン!派)

とまぁいろいろもっともらしい対策が書かれてたりしますが、どーみてもエラー報告の限りでは無関係っぽい死に方です(後述)。

この問題に長期間に渡って放置プレイだったんですが、Adobe は Photoshop Elements12 / CS5 で突如 PhotomergeUI プラグインを削除して機能ごと焼き払うという手段に出ました、これについては

  • (通常級)修正しない?
  • (比較級)修正できないのか?
  • (最上級)修正したくないのか?
  • (椎野級)修正する度胸もないのか?

椎野四段活用で野次りたくもなりますが、まぁ Adobe らしい最後といえる、クリエイティブクラウド(笑)

@Windowsエラー報告から原因を推察する

問題の例外コードを確認すると

問題の署名:
  問題イベント名:	APPCRASH
  アプリケーション名:	Photoshop.exe

  (中略)

  例外コード:	c0000005

  (後略)

すなわち EXCEPTION_ACCESS_VIOLATION(c0000005) なので考えられる原因としては

  1. 単純にバッファオーバーフローとかヌルポ参照のバグ
  2. UACとかユーザー権限に関するセキュリティ保護機能にひっかかってる
  3. DEPとかASLRのようなメモリに関するセキュリティ以下同文

ちゅーとこですな。

まずこのうち 2. と 3. でない事を確認するのに UACを無効にしたり EMETを使って DEP や ASLR を無効 *2にして試してみましたが改善しないので、もっとショボいバグなんでしょう。

@ワイ、バグの原因をほぼ特定して泣く

結論としては、PhotomergeUIプラグインのコーディングが糞でバッファオーバーランしてるみたいですな。そんでそのバッファサイズは MAX_PATH絡みでほぼ確定。

Windowsにおいて、エクスプローラーやコマンドプロンプト、PowerShellからファイルを作成する時にパスの長さはこのMAX_PATHの制限を受けます。

PS D:\> "壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍
六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍
六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍
六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍
六七八九零壱弐参四".length
244
PS D:\> mkdir 壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参
四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参
四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参
四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参
四伍六七八九零壱弐参四


    ディレクトリ: D:\


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        2014/06/13      2:06            壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七
                                             八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四
                                             伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱
                                             弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八
                                             九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍
                                             六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐
                                             参四伍六七八九零壱弐参四伍六七八九零壱弐参四


PS D:\> "壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍
六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍
六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍
六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍
六七八九零壱弐参四伍".length
245

PS D:\> mkdir 壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参
四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参
四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参
四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参
四伍六七八九零壱弐参四伍
New-Item : 指定されたパス、ファイル名、またはその両方が長すぎます。完全限定型名は 260 文字未満で指定し、ディレクトリ名
は 248 未満で指定してください。
発生場所 行:38 文字:24
+         $scriptCmd = {& <<<<  $wrappedCmd -Type Directory @PSBoundParameters }
    + CategoryInfo          : WriteError: (D:\壱弐参四伍六七八九零壱弐...壱弐参四伍六七八九零壱弐参四伍:String) [New-It
em]、PathTooLongException
    + FullyQualifiedErrorId : CreateDirectoryIOError,Microsoft.PowerShell.Commands.NewItemCommand

PowerShellからmkdirを実行した時のエラーメッセージが判りやすいすね「ドライブ名を含む完全パス(完全限定型名)でUCS4で260文字制限(フォルダは更に248文字制限) *3」ですな。

ファイルのMAX_PATH(=260)文字制限、フォルダの248文字制限はそれぞれ CreateFileCreateDirectoryの Windows API の制限でありますが、今回のバグはこのMAX_PATHについて

  • 文字数=バイト数だよ
  • 文字数=ワイド文字(UCS4)数だよ

どっちなのか、解釈がわかれてしまったことによる悲劇ですね。

Windows 7のシェルはワイド文字数だとして扱うけど、Photoshop Photomergeはバイト数だと解釈してパノラマ合成したファイルを出力するパス名用のバッファに

char merged_filepath[MAX_PATH]; 

というコーディングをしてしまっとるのでしょうな。

んで、このバッファにMAX_PATH分のUCS4文字(つまりUTF-8ならMB_LEN_MAX=4ですので最大 260*4=1040byte)をガッツリ書き込んで クラッシュ、嗚呼。

@ちゅうことで回避策

エンドユーザー様には、D:ドライブ直下に作業用の短い名前のフォルダを作成し、そこにパノラマ結合したいファイルを置いて作業しろと指示しました。 これで一件落着。

@結論

これくらいすぐ原因突き止めて直してもらいたいもんだけど、機能とプラグインごと削除で対応ってAdobeの中の人たちの技術力ってどーなのよ。

ちゅーことでいつもの。

 PATH_MAX「_POSIX_PATH_MAXがやられたようだな…」

 MAXPATHLEN 「ククク…奴は我ら四天王の中でも最弱…」

 FILENAME_MAX「MAX_PATH如きに負けるとは、我らの面汚しよ…」

他にも_XOPEN_PATH_MAXとか f?pathconf(3)とかUNIXプログラミングにも強敵が大勢いるので、使い分けをちゃんと気をつけてプログラミングしようね!

@おまけ

ちなみに Cygwin の mkdir は完全パスでのMAX_PATH制限ではなく 256byte 制限やね、Windows API 関係無しに _POSIX_PATH_MAXが使われてるのだろーか。

$ echo -n 壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零\
壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零\
壱弐参四伍六七八九零壱弐参四伍 | wc -c
255

$ mkdir 壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零\
壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零\
壱弐参四伍六七八九零壱弐参四伍

$ ls
壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍

$ echo -n 壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零\
壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零\
壱弐参四伍六七八九零壱弐参四伍六 | wc -c
258

$ mkdir 壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零\
壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零\
壱弐参四伍六七八九零壱弐参四伍六
mkdir: ディレクトリ `壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六七八九零壱弐参四伍六' を作成できません: File name too long

いいのかなこれ。

*1: SONY のデジカメだと スイングパノラマで撮影した時点で勝手に繋いでくれるんだけどねー
*2:ちな ASLR を無効にすると IE10 以降は起動しなくなるので注意。さらにその状態で IE の再インストールをしようもんなら %windir%\servicing\Packages 以下の整合性がぶっ壊れ、悪名高い WindowsUpdate 9C59 エラーになるので注意、pkgmgrで手動で競合するパッケージをアンインストールする羽目になります。
*3:この260/248文字制限はAPIの制限であって、NTFSそのものはパス名の上限は約32,000文字まで許容しとります。