Safariの子ウインドウ挙動で作るブラウザ障害

主要ブラウザの中で孤高の挙動を保ち続ける、Safari。
最近見つけた、このSafariだけでブラウザ障害を起こす方法を書き殴ってみます。

まず、下の2つのHTMLを準備しましょう。

■ index.html

<!DOCTYPE html>
<html><head><script language="javascript">
<!--
var test = null;
function test1() {
  test = window.open('test.html', 'kowin');
}
function test2() {
  var dum = (test!=""); // これがキモ
  alert('感動のゴール!');
}
-->
</script></head><body>
 <a href="#" onclick="test1()">おぺん</a>
 <a href="#" onclick="test2()">ちぇけら</a>
</body></html>

■test.html

<html><body></body></html>

そして、次の操作をしましょう。
1. index.htmlをブラウザで開く
2. 「おぺん」リンクをクリックして子ウインドウを開く
3. 子ウインドウを閉じる
4. 「ちぇけら」リンクをクリックする

すると…
Safariブラウザ以外では、「感動のゴール!」メッセージが出ますが…
Safariだけ出ません!

なぜなぜ?

閉じられたウインドウの扱いが違う

これをSafariでデバッグすると、index.html側の「これがキモ」とコメントを入れている行で、
TypeError: No default value
の例外が発生していることがわかります。

f:id:osajiru:20141122134159p:plain

ウインドウを表示する前とウインドウを表示している状態で「ちぇけら」リンクをクリックした時は、例外は発生しないです。
ウインドウが閉じられた後だけ発生します。

どうやら、閉じられたウインドウオブジェクトは、Safariでは勝手に破棄されているらしい…
例外が出るif文を
var dum = (test!=null);
に変えた時は発生しません。

空文字と比較しようとすると、オブジェクトの文字列化処理が自動的に走るので、その際に無いオブジェクトの処理を呼び出してますよ的な例外が発生しているようです。

IE、FireFox、Chromeでは、閉じられてもオブジェクトは使用できる状態なので、例外は発生しません。

この挙動でヤバイ障害を起こす

「感動のゴール!」部分が、入力不可制御のようなデータ整合性を保つためのコードだったら… 不整合データが簡単に作れちゃいます。

これはヤバイ!

そんな大事なコードは、環境が分からないクライアント側じゃなく、サーバー側で実装しないとダメですが、結構クライアント側だけでやっているシステムも見かけます…

Safariは、マイナーな上にこんな感じの挙動違いが多いので、これで色んなシステムを突いて回ると、意外なブラウザ障害が見つかるかもです。

© 2009-2017 Osajiru All Rights Reserved.