libpngでの誤用例
libpngライブラリ は、png形式の画像データを扱う定番のライブラリです。さまざまなアプリケーションが libpngライブラリを組み込んで使っています。そのような重要な位置付けにあるライブラリに、「使用上の注意 その1」で説明したような簡単な間違いがひそんでいました。
png形式の画像データは、chunkと呼ぶ単位にまとめられたデータの集まりとして表現されます。chunkには必須の(必ず存在しなければならない)ものと、必須ではない(存在しなくてもよい)ものが定義されています。必須ではないchunkの一つとして「sPLT chunk」があります。画像データを減色して扱うときの補助的な情報を提供するものです。libpngライブラリの内部では、sPLT chunkのデータを格納するデータ構造としてpng_sPLT_tとpng_sPLT_entryという2つの構造体を使っています。
/*
* The following two structures are used for the in-core representation
* of sPLT chunks.
*/
typedef struct png_sPLT_entry_struct
{
png_uint_16 red;
png_uint_16 green;
png_uint_16 blue;
png_uint_16 alpha;
png_uint_16 frequency;
} png_sPLT_entry;
typedef png_sPLT_entry FAR * png_sPLT_entryp;
typedef struct png_sPLT_struct
{
png_charp name; /* palette name */
png_byte depth; /* depth of palette samples */
png_sPLT_entryp entries; /* palette entries */
png_int_32 nentries; /* number of palette entries */
} png_sPLT_t;
sPLT chunkに対応するデータ構造はpng_sPLT_tです。sPLT chunkには複数のパレット情報を含めることができるため、個々のパレット情報を独立した構造体 png_sPLT_entryに格納し、png_sPLT_t構造体には png_sPLT_entryの配列へのポインタを持たせています。
さて、libpngライブラリが提供する関数の中に、sPLT chunkを組み立てるライブラリ関数 png_set_sPLT()がありました。この関数の中で、sPLT chunkのために動的にメモリを確保しています。そのときにやってしまったのが2つの構造体の取り違いでした。個々のパレット情報を入れる構造体png_sPLT_entryのためのメモリ領域を確保しようとして、malloc()の引数にpng_sPLT_tのサイズを指定していたのです。
これを修正するパッチは単純で、sizeofの引数に指定する構造体の名前を直すだけです。ライブラリ自身のソースコードの修正は単純ですが、システム全体の対応は、それほど単純ではありません。libpngライブラリを使っているアプリケーションはどれか、それらは静的リンクされているのか動的リンクされているのかをすべて調べ、静的リンクされているアプリケーションについては、修正済みライブラリを使ってコンパイルし直すといった対応が必要になります。
この問題にはCVE-2006-5793という番号が付けられており、DoS攻撃に使われる危険があるとされています。MITREのページで関連情報を見てみると、Linux ベンダやAppleなどに加えて、Google Android SDKにも影響があったことが分かります。
