まとめ
bytes.Buffer.ReadFrom()にダメなio.Readerを渡すとerrorを握りつぶした上で slice bounds out of range
のpanic が発生する場合がある。
起きたこと
aws-sdk-goを使用して暗号化されたS3オブジェクトを読み込むときに slice bounds out of range
のpanicが稀に発生する状況があった(継続中→直りました。中の人ありがとう)
考察
aws-sdkの暗号化されたS3オブジェクトを読むための io.Reader は復号に失敗した場合に暗号文のほうのlengthを返すようなコードになっていた。
本来は引数のdata []byte
に書き込んだ長さを返すべきだし、書き込んでいないなら0を返すべきだった。
これは修正済み。
上記とは別の問題として、Goのbytes.Bufferの実装として、関数を呼び出した後エラーチェックしていないことと、返り値の長さチェックをしていないというのがある。
ただし、io.Readerの定義では、返り値は 0 <= n <= len(p)
でないといけない(pは引数の[]byte
)ので、正しいといえば正しい。
しかしerrorが返ってくるパターンでも、正しくない値が返されてしまうと、errorを無視してしまうコードになっている。
golang的にはerrorをまず確認すべきじゃないかと思う。
(思ったのでPR出したけど、後方互換性に影響がありそうなので取り下げた)
なお ioutils.ReadAll()
や io.Copy()
でも同じ状態になる。