Python

【対処法】Pillowで「DecompressionBombWarning: Image size (◯◯pixels) exceeds limit of 89478485 pixels, could be decompression bomb DOS attack.」が出た!

みなさん、Pillowってご存知ですか?

ざっくり言うと、Pythonで使用することができる画像操作用のライブラリです。
ImageMagickと似たようなものですが、ImageMagickよりもコンパクトで高速なライブラリになります。

そんなPillowですが、先日の業務で初めて触る機会を得ました。
実際に触ってみると、思っていたよりも簡単に利用することができ、便利なライブラリだなと思いました。

さて、業務では画像の背景透過処理に用いていたのですが、その途中で表題のワーニングが発生し、しかも処理が固まったように見えたのです。

しばらくすると処理自体は無事に終わったので良かったのですが、ワーニングを見たときにはちょっと焦ってしまったので、このときに調べた内容を記事にしようと思います。
私と同じようにびっくりしてしまう人がいるかもしれないですしね。

そんなわけで、今回はPillowで「DecompressionBombWarning: Image size (◯◯pixels) exceeds limit of 89478485 pixels, could be decompression bomb DOS attack.」が出た場合の対処法についてご紹介しますね。

「DecompressionBombWarning: Image size (◯◯pixels) exceeds limit of 89478485 pixels, could be decompression bomb DOS attack.」の意味とは?

このワーニングは、処理中の画像サイズが基準サイズを超えている場合に表示されるようです。

公式ドキュメントには以下のようにあります。

To protect against potential DOS attacks caused by “decompression bombs” (i.e. malicious files which decompress into a huge amount of data and are designed to crash or cause disruption by using up a lot of memory), Pillow will issue a DecompressionBombWarning if the image is over a certain limit.

Pillow公式ドキュメント Image Module#Functions より

大量のデータが送られてきた場合にDOS攻撃を防ぐためにワーニングを表示しているようですね。

つまり、「設定された最大データサイズを超えるデータが来ています。もしかして攻撃されていませんか?」と注意を促してくれているわけですね。

そのプログラムに画像データを投入しているのがご自身の場合はひとまず問題ありません。

データが多いため、一見すると処理が止まっているかのように見えてしまうかもしれませんが、そのまま待てばデータ処理は無事に完了するので、しばらく放置してみてくださいね。

DecompressionBombWarningを非表示にする方法は?

ローカルで実行する場合など、そもそもDOS攻撃の可能性がない場合には、ワーニングが邪魔になるかもしれません。

そのような場合に備えて、このワーニングを非表示にする方法もあります。

こちらが参考になりました。
Help explain/control large image warnings from Pillow
Image Cropping Tool (Python)

こちらのissueとstackoverflowで示されている方法は以下の3つです。

  1. 画像データの最大サイズを変更する
from PIL import Image
Image.MAX_IMAGE_PIXELS = 1000000000    
  1. 画像データの最大サイズのチェックを無効にする
from PIL import Image
Image.MAX_IMAGE_PIXELS = None
  1. ワーニングをフィルターしてしまう
import warnings
from PIL import Image
warnings.simplefilter('ignore', Image.DecompressionBombWarning)

これらのいずれかの対応を行うとワーニングが非表示になります。

ちなみに、私は1番の対応を選びました。

DecompressionBombWarningをエラーとしてキャッチしたい

一方で、警告ではなくてエラーにして例外をキャッチしたい、という方もいると思います。

その場合は、さきほどのissueでもstackoverflowでも示されていましたが、以下のようにDecompressionBombWarningをエラーとしてフィルターしてしまえばOKです。

from PIL import Image                                                                                         
Image.warnings.simplefilter('error', Image.DecompressionBombWarning)

こうすれば大きいサイズの画像を読み込まなくなりますね。

終わりに

今回はPillowで「DecompressionBombWarning: Image size (◯◯pixels) exceeds limit of 89478485 pixels, could be decompression bomb DOS attack.」が出た場合の対処法についてご紹介しました。

内容をまとめると以下のようになります。

まとめ
  • 一見処理が止まったように見えるが、実は裏で処理は動き続けている。
  • ワーニングを消す場合は、以下のいずれかを行えばOK
    ・「Image.MAX_IMAGE_PIXELS = 1000000000 」と記述する
    ・「Image.MAX_IMAGE_PIXELS = None」と記述する
    ・「warnings.simplefilter(‘ignore’, Image.DecompressionBombWarning)」とフィルターする
  • エラーとしてキャッチしたい場合は、「Image.warnings.simplefilter(‘error’, Image.DecompressionBombWarning)」とフィルターする

一見処理が止まってしまったように見えますが、裏ではしっかりと処理をしている最中ですので、落ち着いて待ってみてください。
しばらく待つと処理が進行するはずです。

ワーニングを消したいという方は、今回のまとめのように対応してみてくださいね。

今回はここまでです。それでは。