642日前に日本中を震撼させた闇の魔術に対する防衛術 の授業

**[闇の魔術に対する防衛術 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/yaminomajutu)** を完走するため、深夜のテンションで書き殴ったポエムです。(4日目)

明日(5日目)は、**@taptappun** さんによる **Github Hacking ~Githubを容量無制限のクラウドストレージとして使用する試み~** です。

※ 2020/12/04 21:54 大幅に加筆/修正しました

---

先生「本日は **日本中を震撼させた闇の魔術** に対する防衛術を教えます。皆さんは、 **今日から遡ること642日前** 、日本中を恐怖に陥れた、 言葉に出すのも躊躇われる、 **あの呪い** を知っていますか？」

ぼく「はい。Qiitaでも多くの記事が上がっていたので覚えています。」

先生「あの呪いの恐ろしいところは、 **ほんとうに何気もない、日常生活で気にもとめないほど、ありふれた魔法** が、あの日を境に、**あの呪いが発現したこと** によって、 **命を落としかねない危険な魔法** に変わってしまったことです。」

ぼく「はい。Qiitaでも消息が途絶えたような、恐ろしい記事を見たように思います。」

先生「当時、その呪いを解くために多くの人が戦いました。 **自ら呪いにかかるリスクを負ってでもも、星を背負い、呪いを解こうと戦った魔法使い** は数千人にのぼり、 **始まりの魔術師と呼ばれるような、偉大な魔法使い** も戦いに加わりました。」

ぼく「はい。twitterを見て大変興奮したのを覚えています。」

先生「それでも、 **呪いを完全に解くことはできなかった** のです。呪いの効力は弱まったといわれていますが、**また、いつ呪いが発現するかは分からない** のです。」

ぼく「それは、とても怖いですね。」

先生「しかし、呪いの内容が分かっていれば、事前に、 **祈りの魔法を唱えることで呪いを打ち消す** ことができます。本日は、言葉に出すのも躊躇われる、 **あの呪い** に有効な `<script>` を考えましょう。」

ぼく「わかりました！よろしくお願いします！」

先生「**あの呪い** の特徴は、**無限** と **`alert`** です。この特徴を事前に知っていれば、祈りの魔法も作成できるでしょう。あなたなら、どんな `<script>` を書きますか？」

ぼく「そうですね。無限に `alert` を呼んでも大丈夫なように、 `alert` 自体が一定回数以上を呼ばれたら、何もしないような制限をかける`<script>` はどうでしょうか。」

``` javascript
var _alert = window.alert;
var _alert_cnt = 0;
window.alert = (arg) => {
  if (_alert_cnt < 5) {
    _alert(arg);
  }
  _alert_cnt += 1;
};
```

先生「発想は非常によいですね。ここでは、グローバル変数名の衝突などの細かい点は無視します。いわゆる **モンキーパッチ** という種類の魔法ですね。確かにこのコードを事前に実行すれば、無限に `alert` が呼ばれても、 **途中からダイアログが表示されなくなる** ため、**あの呪い** には有効でしょう。しかし、このコードでは **通常 `alert` を使う上では問題が発生** しませんか？ `alert` が 5回呼ばれてしまうと、以降 `alert` が使えなくなってしまいますね。」

ぼく「そうですね。それでは、`alert` の前後でタイマーを挟んだ以下のような `<script>` はどうでしょうか。」

``` javascript
var _alert = window.alert;
var _alert_cnt = 0;
var _alert_last = Date.now();
window.alert = (arg) => {
  let now = Date.now();
  if (now - _alert_last < 1000) {
    if (_alert_cnt < 5) {
      _alert(arg);
      _alert_cnt += 1;
    }
    _alert_last = Date.now();
  } else {
    _alert(arg);
    _alert_cnt = 0;
  }
};
```

先生「そうですね。これなら、**ダイアログをとじて、すぐにまたダイアログが開いた** 、ということが　**連続** しなければ、 `alert` を何回でも使えますね。」

ぼく「はい。この祈りの魔法を事前に唱えれば、 **あの呪い** は、もう怖くないのでしょうか？ 」

先生「そうですね。それでは、実際に試してみましょう。今から、この祈りの魔法を事前に唱えます。その後、あの呪いが発現するかもしれない魔法をかけます。準備はいいですか。では、」

ぼく「！！！」

先生「`while(true) { alert(1); }` ！ 」

OKボタンを押す音『ポチ、ポチ、ポチ、ポチ、ポチ』

ブラウザのタグ『ぐるぐるぐるぐるぐるぐるぐるぐる。。。』

ぼく「！！ぐるぐるが止まらない！！」

先生「そうです。あなたは、 **`alert` が無限に呼ばれたら、何もしないように、つまり、スキップする魔法** をかけました。そのため、ダイアログは出なくなりました。しかし、**無限にループが行われる状態は変わっていない** のです。」

ぼく「！！！」

先生「**あの呪い** の細かい条件とは違います。しかし、ダイアログが止めれなかったように、ぐるぐるも止めれません。今は目が回る程度のものでしょう。しかし、 **あの呪い** の効力が弱まっていなかったら、あなたの存在が消されていたかもしれません。」

ぼく「！！！！！」

先生「これは、**あの呪い** の条件とは異なりますが、CPUに負荷をかけています。CPUの負荷に関わる別の呪いを聞いたことはありませんか？」

ぼく「知っています！ **あの呪い** より少し前に発現した呪いですね。」

先生「良く知っていますね。CPUは呪いに関係ないと思われていた常識をひっくり返したことで有名な呪いです。呪いは身近なところにも潜んでいるのです。」

ぼく「・・・」

先生「それでは、祈りの魔法に戻りましょう。`<script>` をどのように修正すればよいですか？」

ぼく「うーん。。 `javascript` は非同期プログラミングなので、 `sleep` で処理の途中でCPUを休ませることはできないし。」

先生「無限のほうを何とかすることはできませんか？」

ぼく「無限ループを、関数の中から抜ければ、、そうか！ **例外を投げればいいのか！** 」

``` javascript
var _alert = window.alert;
var _alert_cnt = 0;
var _alert_last = Date.now();
window.alert = (arg) => {
  let now = Date.now();
  if (now - _alert_last < 1000) {
    if (_alert_cnt < 5) {
      _alert(arg);
      _alert_cnt += 1;
    } else {
      throw 'Help Me!!';
    }
    _alert_last = Date.now();
  } else {
    _alert(arg);
    _alert_cnt = 0;
  }
};
```

先生「よく気づきましたね。それでは早速`while(true) { alert(1); }`」

ぼく「！！！！！」

先生「どうですか？」

ぼく「ぐるぐるはなくなりました。けど、そのぶん **殴られたような痛みを感じた** のですが。。。(血が出ている)」

先生「それは、 **魔法を無理やり中断した痛み** ですね。中断したことにより怪我をすることもあります。」

ぼく「・・・」

先生「しかし、覚えておいてください。 **魔法は、失敗すれば自分に返ってきて怪我をすることがあります** 。大事故になれば、それこそ元には戻らないような酷いけがを負うこともあるでしょう。」

ぼく「・・・」

先生「それでも、魔法を使えなくなることはありません。呪いの恐ろしい事は、それが魔法自体が使えなくするような、存在自体がなくなるような事態を引き起こすことです。」

ぼく「！」

先生「**あの呪い** に対する祈りの呪文はここまでです。ここまでの授業を受けてどう感じましたか？」

ぼく「呪いは恐ろしさはよくわかりました。しかし、今日作った祈りの呪文は **あの呪い** には有効ですが、副作用もありました。本当にこれが正しい対応なのでしょうか？」

先生「いい質問ですね。今回の　**モンキーパッチという種類の魔法は、一般的に推奨されていません** 。モンキーパッチは、自然の摂理に干渉します。自然の摂理に干渉することは、予期せぬ問題を引き起こすものです。呪いが怖いからといって、安易にモンキーパッチを使ってはいけません。」

ぼく「それでは、どうして今日このような授業を行ったのですか？」

先生「はい。それは、**あの呪い** もまた自然の摂理に関わる呪いだからです。**あの呪い** の恐ろしさはこの点にあります。自然の摂理に関わる呪いに対抗するには、自然の摂理に干渉しなければならないのです。」

ぼく「でも、それでは、また別のこのような呪いが発現したらどうすればいいのでしょうか？自然の摂理が壊れ、魔法を使えない世の中になってしまうのでは・・・」

先生「はい。その通りです。そのために、 **あの呪い** との戦いに多くの魔法使いが加わったのです。 **呪いに対しては、自分の身を守る為だけの祈りの魔法を使うのではなく、決して諦めず、力を合わせ、勇敢に戦い、呪い自体を解く必要がある** のです。」

ぼく「そうだったんですね。僕も呪いに怯えるのではなく、呪いが発現しても諦めずに戦えるように、日々魔法の修練に励もうと思います。」

先生「よく理解してくれましたね。それでは、本日の授業を終わりにします。」

---

深夜のテンションなのでお許しを。