Pillow: 幅が0の画像における _imagingmorph での範囲外アクセス
### 概要
PPM または PGM ファイルは、幅を 0 と宣言することができます。Pillow はこれを許容し、`(0, N)` のサイズの画像を作成します。この画像を `ImageMorph.MorphOp.apply()` に渡すと、ネイティブのモルフォロジー処理コードが `outrow[width - 1]` の行バッファにアクセスします。幅が 0 の場合、これは `outrow[-1]` になります。この処理により、プログラムがクラッシュします。
### 詳細
PPM パーサーは、下限チェックなしで幅と高さを読み込みます。
- `src/PIL/PpmImagePlugin.py:119`
ネイティブの `apply()` 関数は、幅が正であるかどうかを確認せずに、行の端を書き込みます。
- `src/_imagingmorph.c:81` が `outrow[0] = outrow[width - 1] = 0;` を設定します。
`match()` 関数と `get_on_pixels()` 関数も、同じエッジインデックスのパターンを使用しています。
### 実証コード
```python
from PIL import Image, ImageMorph
# 幅が 0 の画像 (作成された PPM ヘッダーからも生成可能)。apply() はネイティブコードで
# outrow[width - 1] == outrow[-1] にアクセスします。
im = Image.new("L", (0, 5))
ImageMorph.MorphOp(op_name="dilation4").apply(im)
```
実行結果:
```
$ python 03_poc.py
Segmentation fault (core dumped)
```
コミット `3e2ab96` のソースコードで確認されました。
AddressSanitizer を使用した場合:
```
==ERROR: AddressSanitizer: SEGV on unknown address (pc ... in apply)
#0 apply src/_imagingmorph.c:81
SUMMARY: AddressSanitizer: SEGV src/_imagingmorph.c:81 in apply
```
幅が 0 の場合、`outrow[width - 1]` への書き込みは、マップされていないページに到達するため、レッドゾーンのオーバーフローではなく、SEGV として現れます。
### 影響
C拡張機能における範囲外書き込み。信頼できない入力から開かれた画像に対してモルフォロジー演算を実行するすべてのアプリケーションに影響を与えます。結果として、プログラムがクラッシュし、メモリの破損が発生する可能性があります。
影響を受けるパッケージ:
- pip (Python) Pillow: 影響を受けるバージョンは 12.3.0 以前、13.0.0 で修正されました。