getChannels() crashes on servers returning an empty channels array — the guard exists in process_trigger_result() but not here
評価
調査の方向性
src/Pusher.php の getChannels() から始め、channels の処理を、オブジェクトでないレスポンスをすでに保護している process_trigger_result() と比較します。空の channels 配列を指定してメソッドを実行し、TypeError なしでドキュメントに記載された配列形式を返すことを確認します。既存の動作が維持されていることを確認するため、関連するプロジェクトのテストを実行します。
索引モデルが issue の本文から書いたものです。
説明
Summary
getChannels() calls get_object_vars() without a type check, so a server response where channels is an empty JSON array crashes the client:
TypeError: get_object_vars(): Argument #1 ($object) must be of type object, array given
src/Pusher.php:664
The interesting part: this library already guards against exactly this, but only on one code path.
process_trigger_result() (added in #323, fixing #322) checks the type:
https://github.com/pusher/pusher-http-php/blob/master/src/Pusher.php#L1195-L1197
if (property_exists($result, 'channels') && is_object($result->channels)) {
$result->channels = get_object_vars($result->channels);
}
getChannels() does not:
https://github.com/pusher/pusher-http-php/blob/master/src/Pusher.php#L660-L666
public function getChannels(array $params = []): object
{
$result = $this->get('/channels', $params);
$result->channels = get_object_vars($result->channels);
return $result;
}
Why it happens in practice
Pusher-protocol implementations other than Pusher itself are common now (Reverb, Sockudo, Soketi). I hit this with Laravel Reverb v1.11.1, which serialises an empty channel list as [] instead of {} — I reported it there as laravel/reverb#402, and it should be fixed on their side too.
But the failure mode is worth guarding here regardless, because it is silent and intermittent: the response is an array only while no channel is occupied. One connected client turns the PHP array into a string-keyed map, json_encode emits an object, and the crash disappears. So it reproduces on idle systems and vanishes under load.
Measured side by side, same signed request:
Reverb → {"channels":[]}
Sockudo → {"channels":{}}
Suggestion
Apply the same guard that process_trigger_result() already uses:
$result->channels = is_object($result->channels) ? get_object_vars($result->channels) : (array) $result->channels;
This keeps the documented return shape (channels as an array of channel names) for every server, instead of a fatal error for some of them. Happy to send a PR.
Environment
- pusher/pusher-php-server ^7.2
- PHP 8.3
- 主要言語
- PHP
- スター
- 1.5k
- フォーク
- 318
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドなし
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
pusher/pusher-http-php のほかの issue
-
`path` option is dropped from request URLs when it has no trailing slash対応中かも @RaphaelFakhri が 4 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
pusher/pusher-http-php#411 ·
pusher/pusher-http-php の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
shukiv/jabali-panel#2423 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 67/100
-
難易度 1/5 1時間未満 初心者へのやさしさ 79/100
smarty-php/smarty#1220 ·
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
StarCitizenWiki/mediawiki-extensions-EmbedVideo#224 · コメント 1 件 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 69/100
opnsense/core#11171 · リアクション 1 件 ·
メンテナーはふだん 1 日以内に返信