風柳メモ

ソフトウェア・プログラミング関連の覚書が中心

Google Chromeのbackground_pageで一定長以上の文字列を扱うとクラッシュすることがある

Google Chromeで、拡張機能の再読み込みや(ブラウザの)再起動を繰り返していたら、突然特定の拡張機能がクラッシュするようになり、以降は当該拡張機能は再読み込みやChromeの再起動を実施(タスクマネージャにて、いったんchromeがすべてなくなっているのは確認済)しても必ずクラッシュしてしまい、Windowsを再起動するしか無くなる、という現象に悩まされていましたいます。

とりあえず、Chrome 10.0.648.205/Windows XP SP3で現象の発生を確認。

調べてみたところ、

  • background_pageにて一定長以上の文字列を扱うと、クラッシュする状態

になっているらしい、ということが解りました。

上記現象が発生した状態で、background_pageに

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
for (var ci=0,s=[]; ci<569280; ci++) s[ci]='A'; s=s.join(''); alert(s);	// OK
for (var ci=0,s=[]; ci<569281; ci++) s[ci]='A'; s=s.join(''); alert(s);	// NG(crush)
</script>
</head>
<body>
</body>
</html>

のように記述した拡張機能を起動すると、2個目のalert(s)でクラッシュしてしまいます(try{}catch(e){}でも捕捉出来ません)。
ちなみに、alert(s.length)は動作します。
569281という数字がマジックナンバーなのか(常に同じ数字になるか)どうかまでは不明。
【2011/06/04追記】その後発生したときには、233409でクラッシュしたので、状況により変化する模様。

例えばAutoPatchWorkの場合だと、background_pageとなっているindex.htmlから呼び出すStorage.js内のStorage.has()で

		has:function(key){
			if (localStorage[key] === void 0) {
				return false;
			}

のようになっていますが、keyが'siteinfo_wedata'で、localStorageに中身(siteinfoを文字列化したもの:2010/06/04時点で700,000文字以上)がある場合、localStorage[key]を評価した時点でクラッシュしてしまいます。

同様に、Storage.set()で

			localStorage.setItem(key, JSON.stringify(data));

のようにしていますが、'siteinfo_wedata'だと、JSON.stringfy()した結果を設定しようとした段階で、クラッシュします。

また、Storage.get()では、

					localStorage.removeItem(key);

のような処理がありますが、keyに対応する内容が一定サイズ以上の文字列の場合、localStorage.removeItem()をコールすると、他の拡張(localStorageを使っている/いないに関わらない)を巻き込んでクラッシュしてしまうこともあるようです。

では、どうすればよいか?

今のところ(OSを再起動する以外に)確実に回避もしくは復旧する方法は掴めていません。
ただ、いろいろと試した後、

  • アドレスバーからjavascript:(function(c,s){for(;c<569281;c++)s[c]='A';s=s.join('');alert(s)})(0,[])としても、クラッシュしなかった*1
  • 上記を実行してから、当該拡張機能を再読み込みしたところ、正常に起動した。

ということで、もしかすると、

javascript:(function(c,s){for(;c<1000000;c++)s[c]='A';s=s.join('');if(s){}})(0,[])

のようなブックマークレットを登録しておけば、いざというときに緊急回避出来るかも知れません。
とりあえず、再現待ちかな〜。
【2011/06/04追記】
その後同現象が発生したときに上記ブックマックレットを実行してみたところ、文字長制限は緩和されたように思えたが、別の要因で(?)クラッシュするようになってしまった模様。結局OS再起動するしかなさげ。詳細な原因は追えていない。

*1:ちなみに、alert()の制限なのか、724961文字以上だと実行できずに「ウェブページの表示中に問題が発生しました」となってしまいます→【2011/06/04追記】その後発生した際には、233441文字で実行出来なくなりました。これも状況によって変化する模様。またこのときにはbackground_pageは233409文字でクラッシュしたが、数字の近さに意味があるのかどうかは不明。