簡単に言えばバグです

  • 投稿日:
  • by
  • カテゴリ:

Movable Typeで、basenameが重複してしまう問題。これ簡単に言うとバグです。

ファイル名の生成は lib/MT/Util.pmの make_unique_basename()という関数が行っています。実際には、下請けの_get_basename()という関数がするのですが、こいつがバグバグでした。

まず、キャッシュを調べて、キャッシュに数値サフィックスの最大値があれば、それを++してbasenameを生成します。

なかった場合に、既存のサフィックスを調べて、その中から最大値を出すのですが、これが見事なまでアフォでした。

まず、ファイル名でソートして、一番大きなものを取り出します。が、ここで2秒考えれば判るように「大きい」がくせ者なのです。この場合の「大きい」は文字列として評価したときに「大きい」であって数値として「大きい」ではないのです。なので、ファイル名が '_1'から始まり'_999'を超えて、4桁に至ったとき、または5桁に至ったときに問題が発生します。もっと早く2桁の時にもでますね。今まででなかったのはv5のそれと処理を微妙に変えてきているからです。

つまり、post_1000というファイル名よりもpost_999の方が大きいと評価されるのです。で、999を持って来て、+1して1000を試すのですが、これは既に存在するので、post_1000はダメで、次を取りに行きます。次が_998です。ここでpost_999が存在しているので、この試行も失敗するはずなのですが、アフォなことに、最初の「大きい」奴をダブらず取り出すために、既に一回取り出した奴は除外する指定をある変数に設定しているのですがこれをそのままにして、存在確認をしに行くため、_999は取り出されず、post_999を作ってもいいかのように結果を返すのです。バカですアフォです。とんでもないバグです。よくもまあこんなものを平気な顔してリリースできるものです。

普段はおそらくはキャッシュが機能するのでしょう。でも、キャッシュが機能しなくなった途端に、破綻が訪れます。同じファイル名を延々と生成し続けます。

このバグは、次の一行を挿入することで回避できますが、サフィックスが多くなると、とても遅くなります。正直言って、どこのバカが考えたコードなのか小一時間問い詰めたくなります。

1311              $base_num = $num + 1;  
1312              delete $terms{id}; 
1313              my $test = $class->load(

このコードの問題は、ファイル名を取り出すときに数値として、或いは、長いものの方が大きいと評価されるようになればいいのですが、このあたりがどうなっているのかはまだ突っ込んで調べてないので、もうしばらくかかりそうです。