frei

旧「anney's room」からブログ「frei」だけ引っ越し&残しました

getcode。

第二弾リリースを控え、検証していただいてたら

今回手を入れてないところで、突然落ちてる箇所があった模様。

調べてみると Jcode の jfold で大量の全角文字を与えると

die するっぽい。

具体的にコード示すと、こう。

#!/usr/bin/perl -w

use strict;

use Jcode;

my $length = 18500;

my $body = '1' x $length;

Jcode->new($body)->jfold(10)->euc();

exit;

開発環境では、たまたま core が吐かれる設定になってたので

そいつを探れば、何処でコケてるのか、具体的にわかるかも。

って、「そもそも大量の全角文字なんか与えるなよっ」って事は

重々承知の上ですが。

それにしても、私、C使いじゃないし、よくわからんなー。

てなこったで、週末家で勉強してきまーす、と宣言して

会社から引き上げたのでした。

かくして、まずは自宅の環境で

どうすりゃいいのか、ググってみる。

・core はくように設定(bash

ulimit -c unlimited

gdbデバッグ

gdb perl coreファイルパス

おっし、ほんじゃ、早速挑戦してみますかー。

えいやっ。

[anigon@localhost jfold]$ gdb perl core.4182

GNU gdb Red Hat Linux (6.3.0.0-1.153.el4rh)

Copyright 2004 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB. Type "show warranty" for details.

This GDB was configured as "i386-redhat-linux-gnu"...(no debugging symbols found)

Using host libthread_db library "/lib/tls/libthread_db.so.1".

warning: core file may not match specified executable file.

./test.pl'.erated by `/usr/bin/perl -w

Program terminated with signal 11, Segmentation fault.

Reading symbols from /usr/lib/perl5/5.8.5/i386-linux-thread-multi/CORE/libperl.so...(no debugging symbols found)...done.

Loaded symbols for /usr/lib/perl5/5.8.5/i386-linux-thread-multi/CORE/libperl.so

Reading symbols from /lib/libresolv.so.2...(no debugging symbols found)...done.

Loaded symbols for /lib/libresolv.so.2

Reading symbols from /lib/libnsl.so.1...(no debugging symbols found)...done.

Loaded symbols for /lib/libnsl.so.1

Reading symbols from /lib/libdl.so.2...

(no debugging symbols found)...done.

Loaded symbols for /lib/libdl.so.2

Reading symbols from /lib/tls/libm.so.6...(no debugging symbols found)...done.

Loaded symbols for /lib/tls/libm.so.6

Reading symbols from /lib/libcrypt.so.1...(no debugging symbols found)...done.

Loaded symbols for /lib/libcrypt.so.1

Reading symbols from /lib/libutil.so.1...

(no debugging symbols found)...done.

Loaded symbols for /lib/libutil.so.1

Reading symbols from /lib/tls/libpthread.so.0...(no debugging symbols found)...done.

Loaded symbols for /lib/tls/libpthread.so.0

Reading symbols from /lib/tls/libc.so.6...(no debugging symbols found)...done.

Loaded symbols for /lib/tls/libc.so.6

Reading symbols from /lib/ld-linux.so.2...

(no debugging symbols found)...done.

Loaded symbols for /lib/ld-linux.so.2

Reading symbols from /usr/lib/perl5/5.8.5/i386-linux-thread-multi/auto/Encode/Encode.so...(no debugging symbols found)...done.

Loaded symbols for /usr/lib/perl5/5.8.5/i386-linux-thread-multi/auto/Encode/Encode.so

Reading symbols from /usr/lib/perl5/5.8.5/i386-linux-thread-multi/auto/Encode/Unicode/Unicode.so...(no debugging symbols found)...done.

Loaded symbols for /usr/lib/perl5/5.8.5/i386-linux-thread-multi/auto/Encode/Unicode/Unicode.so

Reading symbols from /usr/lib/perl5/5.8.5/i386-linux-thread-multi/auto/List/Util/Util.so...done.

Loaded symbols for /usr/lib/perl5/5.8.5/i386-linux-thread-multi/auto/List/Util/Util.so

Reading symbols from /usr/lib/perl5/5.8.5/i386-linux-thread-multi/auto/Encode/JP/JP.so...done.

Loaded symbols for /usr/lib/perl5/5.8.5/i386-linux-thread-multi/auto/Encode/JP/JP.so

#0 0x00aff733 in Perl_regclass_swash () from /usr/lib/perl5/5.8.5/i386-linux-thread-multi/CORE/libperl.so

(gdb)

んあー。漠然としてますな…orz

じゃあ、これでどうだ!

(gdb) run /home/anigon/jfold/test.pl

Starting program: /usr/bin/perl /home/anigon/jfold/test.pl

(no debugging symbols found)

(no debugging symbols found)

(no debugging symbols found)

(no debugging symbols found)

(no debugging symbols found)

(no debugging symbols found)

(no debugging symbols found)

(no debugging symbols found)

[Thread debugging using libthread_db enabled]

[New Thread -1208194848 (LWP 4188)]

(no debugging symbols found)

(no debugging symbols found)

(no debugging symbols found)

(no debugging symbols found)

Program received signal SIGSEGV, Segmentation fault.

[Switching to Thread -1208194848 (LWP 4188)]

0x00aff733 in Perl_regclass_swash () from /usr/lib/perl5/5.8.5/i386-linux-thread-multi/CORE/libperl.so

(gdb)

うーん、やっぱり Perl_regclass_swash のコードを見ろって事ですね。

regexec.c ん中見たけど、

これじゃ、具体的に perl コード中の何処が問題になってるのか

よくわかんないなー。

てな訳で、いつも通りのアプローチで

core は放置(笑)

かくして、jfold を使って、あーだこーだもがいてたんだけど

ふと気付けば、実は jfold 関係なく、

既に jcode->new のタイミングで、落ちている模様。あれれ?

しかも、文字コードeucの時だけ、ダメらしい。

そこで、new のコードを追ってみたら

以下の部分でコケていた。

sub new {

my $class = shift;

my ($thingy, $icode) = @_;

my $r_str = ref $thingy ? $thingy : \$thingy;

my $nmatch;

($icode, $nmatch) = getcode($r_str) unless $icode;

(略)

}

sub getcode {

my $thingy = shift;

my $r_str = ref $thingy ? $thingy : \$thingy;

(略)

$euc += length($1)

while $$r_str =~ /((?:$RE{EUC_C}|$RE{EUC_KANA}|$RE{EUC_0212})+)/go;

お、まさに正規表現使ってますよ。

ほんじゃ、ここだけピックアップして

テストスクリプト書いてみますかー。えいさっ。

#!/usr/bin/perl -w

use strict;

my %RE = (

EUC_0212 => '\x8f[\xa1-\xfe][\xa1-\xfe]',

EUC_C => '[\xa1-\xfe][\xa1-\xfe]',

EUC_KANA => '\x8e[\xa1-\xdf]',

);

my $string = '1' x 100000;

$string =~ /((?:$RE{EUC_C}|$RE{EUC_KANA}|$RE{EUC_0212})+)/go;

exit;

これを実行すると、案の定、

「Segmentation fault (core dumped)」と表示され、core がはかれていたのでした。

じゃ、改めて gdb に登場していただきましょう!と思ったけど

core ファイルパスを指定しても、たいして情報が得られない気がするので(?)

いきなり、run しちゃう方が良いようですね。

GNU gdb Red Hat Linux (6.3.0.0-1.153.el4rh)

Copyright 2004 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB. Type "show warranty" for details.

This GDB was configured as "i386-redhat-linux-gnu"...

(no debugging symbols found)

Using host libthread_db library "/lib/tls/libthread_db.so.1".

(gdb) run /home/anigon/jfold/reg.pl

Starting program: /usr/bin/perl /home/anigon/jfold/reg.pl

(no debugging symbols found)

(no debugging symbols found)

(no debugging symbols found)

(no debugging symbols found)

(no debugging symbols found)

(no debugging symbols found)

(no debugging symbols found)

(no debugging symbols found)

[Thread debugging using libthread_db enabled]

[New Thread -1208543008 (LWP 4438)]

(no debugging symbols found)

(no debugging symbols found)

Program received signal SIGSEGV, Segmentation fault.

[Switching to Thread -1208543008 (LWP 4438)]

0x00afa564 in Perl_regclass_swash ()

from /usr/lib/perl5/5.8.5/i386-linux-thread-multi/CORE/libperl.so

(gdb)

あー、ちゃんと Perl_regclass_swash に辿り着きましたね。

で、そもそも、ここのルーチンのある getcode 関数を通過しているのは

jcode->new する時に、第二引き数を省略しているからで、

その引き数として、最初から文字コード(今回は euc )を設定してやれば

通過しないで済むのでした。

というか、getcode 使う場合は、予め文字数制限して渡さないとアカンのね。