少しイジメテミタ

おっきな SWF ファイル

% php sample/swfdump.phps "魔理沙は大変なものを盗んでいきました.swf" > /dev/null
malloc: ;_;

えっと… swfed は -DMALLOC_DEBUG を付けてコンパイルすると、 free し忘れを検出する為に、malloc/free の管理テーブルを作ります。
そのサイズが足りませんでした。
とりあえずサイズを倍に拡張して足りたので、それで… (このやり方はかっこ悪いので、もう少し考えます)

デバッグ用とはいえ分かりにくいので、エラーメッセージに table full を追加してます。

bcut

バイナリを切り出すプログラムを使って苛めてみました。

中途半端な SWF ファイル

% bcut game.swf 0 900000  >  game-hankake.swf
% php sample/swfdump.phps  game-hankake.swf
swf_object_input: uncompress failed by unknown reason
magic=CWS  version=9  file_length=1063877
rect=(0, 0)-(0, 0) (f_size=0)
frame_rate=0.0  frame_count=0
XXX (3) ptr=0xb79ac008 (/home/yoya/svn/swfed/src/swf_object.c, 61)

メモリリーク発見。(☆▽☆)
zlib 伸張に失敗した時の異常系で、 zlib 用に確保した領域を free し忘れてました。

対処後

% php ~/svn/swfed/sample/swfdump.phps game-hankake.swf
swf_object_input: uncompress failed by unknown reason
magic=CWS  version=9  file_length=1063877
rect=(0, 0)-(0, 0) (f_size=0)
frame_rate=0.0  frame_count=0

よしよし。

中途半端な PNG ファイル

% bcut kuriboo4.png 0 166300 > kuriboo4-hankake.png
% php sample/swfdump.phps game.swf
	<略>
[38] tag=DefineBitsLossless2(36)  length=110
        image_id=30  format=3  width=62  height=18
        colormap_count=16  rgba colormap exists  indices exists
	<略>
% php sample/swfreplacepngdata.phps game.swf 30 kuriboo4-hankake.png > /dev/null
png_data_read_func: ! png_buff->data_offset(160789) + size(5516) <= png_buff->data_len(166301)
libpng error: png_read_read_func failed

アボートしました
あちゃー… でも、libpng のエラーハンドリングは setjmp 方式なんですよね…

libpng の man(3) の説明

See the discussion  on  libpng error handling in the Customizing
Libpng section below for more information on the  libpng
error   handling.    If  an  error  occurs,  and  libpng
longjmp’s back to your setjmp, you  will  want  to  call
png_destroy_read_struct() to free any memory.

    if (setjmp(png_jmpbuf(png_ptr)))
    {
        png_destroy_read_struct(&png_ptr, &info_ptr,
           &end_info);
        fclose(fp);
        return (ERROR);
    }

でもって、

If  you  read
the  file  from  different  routines,  you  will need to
update the jmpbuf field every time you enter a new  rou-
tine that will call a png_*() function.

スコープがあってればイイじゃない。ってとこかしら。

setjmp

png_bytepp png_image_data = NULL;
	<略>
if (setjmp(png_jmpbuf(png_ptr))) {
    fprintf(stderr, "pngconv_png2lossless: libpng error jump occured\n");
    png_destroy_read_struct(&png_ptr, &png_info, NULL);
    if (png_image_data) {
        for ( y = 0 ; y < png_height ; y++) {
            free(png_image_data[y]);
        }
        free(png_image_data);
    }
    return NULL;
}
	<略>
png_image_data = (png_bytepp) malloc(png_height * sizeof(png_bytep));
for (y=0; y < png_height; y++) {
    png_image_data[y] = (png_bytep) malloc(png_get_rowbytes(png_ptr, png_info));
}

としてみたら、png_image_data が free 出来ず。
何でだろうと「setjmp ローカル変数」で google 様にお伺いを立てた所、

xにvolatileをつけ忘れると、こういうこと↑になります…

ナルホド。最適化とレジスタの罠か… やっぱり setjmp キライ
abort しちゃった方が全てを忘れられて楽だけど、そんな訳にもいかないので、頑張って対処します。

discards qualifiers from pointer target type

/home/yoya/svn/swfed/src/swf_png.c: In function 'pngconv_png2lossless':
/home/yoya/svn/swfed/src/swf_png.c:166: warning: passing argument 1 of
 'png_destroy_read_struct' discards qualifiers from pointer target type
/home/yoya/svn/swfed/src/swf_png.c:166: warning: passing argument 2 of
 'png_destroy_read_struct' discards qualifiers from pointer target type

volatile つけたら怒られちゃった… ><
仕方が無いので cast 付けて黙らせます。

png_destroy_read_struct((png_structpp) &png_ptr,
                        (png_infopp) &png_info, NULL);

何だかなぁ…

might be clobbered by 'longjmp' or 'vfork'

/home/yoya/svn/swfed/src/swf_png.c:234: warning:
argument 'image_data' might be clobbered by 'longjmp' or 'vfork'

image_data は setjmp と関係ない所で使ってるのに…

どうしよう…

最後に

やっぱり setjmp キライ