diff options
| author | nsfisis <nsfisis@gmail.com> | 2022-11-19 15:27:26 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2022-11-19 15:27:26 +0900 |
| commit | a0738cdd46d6e52463687b903b1e7d09a541aaa1 (patch) | |
| tree | 1e6a6ab30c8863d0522b1cb1ad9f3d3160845bad | |
| parent | 6209453817da9922f28bac1bb1522c6d380630ab (diff) | |
| download | blog.nsfisis.dev-a0738cdd46d6e52463687b903b1e7d09a541aaa1.tar.gz blog.nsfisis.dev-a0738cdd46d6e52463687b903b1e7d09a541aaa1.tar.zst blog.nsfisis.dev-a0738cdd46d6e52463687b903b1e7d09a541aaa1.zip | |
new post: phperkaigi-2023-unused-token-quiz-2
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | NOTE.md | 1 | ||||
| -rw-r--r-- | content/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2.adoc | 132 | ||||
| -rw-r--r-- | public/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2/index.html | 277 | ||||
| -rw-r--r-- | public/posts/index.html | 16 | ||||
| -rw-r--r-- | public/tags/php/index.html | 16 | ||||
| -rw-r--r-- | public/tags/phperkaigi/index.html | 16 |
7 files changed, 459 insertions, 1 deletions
@@ -27,7 +27,7 @@ gen: .PHONY: local_up local_up: docker-compose -f docker-compose.local.yml up -d - @echo http://localhost:8080 + @echo http://localhost .PHONY: local_down local_down: @@ -45,6 +45,7 @@ $ touch content/posts/$(date +'%Y-%m-%d')/[TITLE].md * [ ] Sitemap * https://www.sitemaps.org/protocol.html * https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap?hl=ja +* [ ] Admonitions ## Structure diff --git a/content/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2.adoc b/content/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2.adoc new file mode 100644 index 0000000..859ab74 --- /dev/null +++ b/content/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2.adoc @@ -0,0 +1,132 @@ += PHPerKaigi 2023: ボツになったトークン問題 その 2 +:tags: php, phperkaigi +:description: 来年の PHPerKaigi 2023 でデジタルサーカス株式会社から出題予定のトークン問題のうち、 \ + ボツになった問題を公開する (その 2)。 +:revision-1: 2022-11-19 公開 + +== はじめに + +2023 年 3 月 23 日から 25 日にかけて開催予定 (記事執筆時点) の https://phperkaigi.jp/2023/[PHPerKaigi 2023] において、 +昨年と同様に、弊社 https://www.dgcircus.com/[デジタルサーカス株式会社] からトークン問題を出題予定である。 + +昨年のトークン問題の記事はこちら: link:/posts/2022-04-09/phperkaigi-2022-tokens/[PHPerKaigi 2022 トークン問題の解説] + +すでに 2023 年用の問題は作成済みであるが、その制作過程の中でいくつかボツ問ができた。せっかくなので、PHPerKaigi 開催を待つ間に紹介しようと思う。 + +10 月から 2 月まで、毎月 1 記事ずつ公開していく予定 (忘れていなければ)。 + +その 1 はこちら: link:/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/[PHPerKaigi 2023: ボツになったトークン問題 その 1] + +== 問題 + +注意: これはボツ問なので、得られたトークンを PHPerKaigi で入力してもポイントにはならない。 + +[source,php] +---- +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +---- + +"And Then There Were None" (そして誰もいなくなった) と名付けた作品。変則 quine (自分自身と同じソースコードを出力するプログラム) になっている。 + +== トークン入手方法 + +実行してみると、次のような出力が得られる。 + +[source,php] +---- +# +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +---- + +1 行目を除き、先ほどのコードとほぼ同じものが出てきた。もう一度実行してみる。 + +[source,php] +---- +# +W +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s='<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +---- + +今度は 2 行目が書き換えられた。すべての行が変化するまで繰り返すと次のようになる。 + +[source,php] +---- +# +W +E +L +O +V +E +P +H +P +---- + +トークン「#WELOVEPHP」が手に入った。 + +== 解説 + +一見すると同じ行が 10 行並んでいるだけなのにも関わらず、なぜそれぞれの行で出力が変わるのか。ソースコードをコピーして、適当なエディタに貼り付けるとわかりやすい。 + +Vim で開くと次のようになる (1 行目を抜粋)。 + +[source,php] +---- +<?php printf((isset($s)?fn($s)=>trim($s,"<200b>"):fn($s)=>chr(strlen($s)/3))($s='<200b><?php printf((isset($s)?fn($s)=>trim($s,"<200b>"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?> +---- + +`<200b>` と表示されているのは、Unicode の U+200b で、ゼロ幅スペースである。 + +NOTE: エディタによっては、ゼロ幅スペースが見えないことがある。VSCode ではブラウザと同様に不可視だった。 + +文字列リテラルの中にゼロ幅スペースを仕込むことで、見た目を変えずに情報をエンコードすることが可能となる。 + +続いて、トークンへの変換ロジックを解析する。注目すべきはこの部分だ。以下、ゼロ幅スペースは Vim での表示に合わせて `<200b>` と記載する。 + +[source,php] +---- +fn($s)=>chr(strlen($s)/3) +---- + +PHP の `strlen()` は文字列のバイト数を返す。1 行目の `$s` は以下の内容となっており、 + +[source,php] +---- +$s='<200b><?php printf((isset($s)?fn($s)=>trim($s,"<200b>"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>' +---- + +このソースコードは UTF-8 で書かれているので、105 バイトになる。それを 3 で割ると 35 となり、これは `#` の ASCII コードと一致する。他の行も、同様にしてゼロ幅スペースを詰めることで文字列長を調整し、トークンをエンコードしている。 + +デコード部以外の部分は、quine のための記述である。 + + +== おわりに + +https://blog.rust-lang.org/2021/11/01/cve-2021-42574.html[CVE-2021-42574] に着想を得た作品。この脆弱性は、Unicode の制御文字である left-to-right mark と right-to-left mark を利用し、ソースコードの実際の内容を欺く、というもの。簡単のためゼロ幅スペースを用いることとし、ついでに quine にもするとこうなった。 + +ボツになった理由は、ゼロ幅スペースを表示してくるエディタが想像以上に多かったため。「同じ行が並んでいるだけなのに出力が異なる」というアイデアの根幹を崩されてしまうので、この問題は不採用となった。 diff --git a/public/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2/index.html b/public/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2/index.html new file mode 100644 index 0000000..8ca3e92 --- /dev/null +++ b/public/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2/index.html @@ -0,0 +1,277 @@ +<!DOCTYPE html> +<html lang="ja-JP"> + <head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta name="author" content="nsfisis"> + <meta name="copyright" content="© nsfisis"> + <meta name="description" content="来年の PHPerKaigi 2023 でデジタルサーカス株式会社から出題予定のトークン問題のうち、 ボツになった問題を公開する (その 2)。"> + <meta name="keywords" content="PHP,PHPerKaigi"> + <link rel="icon" type="image/svg+xml" href="/favicon.svg"> + <title>PHPerKaigi 2023: ボツになったトークン問題 その 2 | REPL: Rest-Eat-Program Loop</title> + <link rel="stylesheet" href="/hl.css"> + <link rel="stylesheet" href="/style.css"> + <link rel="stylesheet" href="/custom.css"> + </head> + <body class="single"> + <header class="header"> + <nav class="nav"> + <p class="logo"> + <a href="/">REPL: Rest-Eat-Program Loop</a> + </p> + </nav> + </header> + <main class="main"> + <article class="post-single"> + <header class="post-header"> + <h1 class="post-title">PHPerKaigi 2023: ボツになったトークン問題 その 2</h1> + + <ul class="post-tags"> + + <li class="tag"> + <a href="/tags/php/">PHP</a> + </li> + + <li class="tag"> + <a href="/tags/phperkaigi/">PHPerKaigi</a> + </li> + + </ul> + + </header> + <div class="post-content"> + <section> + <h2 id="changelog">更新履歴</h2> + <ol> + + <li class="revision"> + <time datetime="2022-11-19">2022-11-19</time>: 公開 + </li> + + </ol> + </section> + + + + + +<section class="section-1"> + <h2 id="" class="section-header"> + + はじめに + + </h2> + <div class="section-body"> + <div class="paragraph"> +<p>2023 年 3 月 23 日から 25 日にかけて開催予定 (記事執筆時点) の <a href="https://phperkaigi.jp/2023/">PHPerKaigi 2023</a> において、 +昨年と同様に、弊社 <a href="https://www.dgcircus.com/">デジタルサーカス株式会社</a> からトークン問題を出題予定である。</p> +</div> +<div class="paragraph"> +<p>昨年のトークン問題の記事はこちら: <a href="/posts/2022-04-09/phperkaigi-2022-tokens/">PHPerKaigi 2022 トークン問題の解説</a></p> +</div> +<div class="paragraph"> +<p>すでに 2023 年用の問題は作成済みであるが、その制作過程の中でいくつかボツ問ができた。せっかくなので、PHPerKaigi 開催を待つ間に紹介しようと思う。</p> +</div> +<div class="paragraph"> +<p>10 月から 2 月まで、毎月 1 記事ずつ公開していく予定 (忘れていなければ)。</p> +</div> +<div class="paragraph"> +<p>その 1 はこちら: <a href="/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/">PHPerKaigi 2023: ボツになったトークン問題 その 1</a></p> +</div> + </div> +</section> + + + + + +<section class="section-1"> + <h2 id="" class="section-header"> + + 問題 + + </h2> + <div class="section-body"> + <div class="paragraph"> +<p>注意: これはボツ問なので、得られたトークンを PHPerKaigi で入力してもポイントにはならない。</p> +</div> +<div id="source." class="listingblock"> +<div class="content"> +<pre class="rouge highlight"><code data-lang="php"><span class="o"><?</span><span class="n">php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span></code></pre> +</div> +</div> +<div class="paragraph"> +<p>"And Then There Were None" (そして誰もいなくなった) と名付けた作品。変則 quine (自分自身と同じソースコードを出力するプログラム) になっている。</p> +</div> + </div> +</section> + + + + + +<section class="section-1"> + <h2 id="" class="section-header"> + + トークン入手方法 + + </h2> + <div class="section-body"> + <div class="paragraph"> +<p>実行してみると、次のような出力が得られる。</p> +</div> +<div id="source." class="listingblock"> +<div class="content"> +<pre class="rouge highlight"><code data-lang="php"><span class="c1">#</span> +<span class="o"><?</span><span class="n">php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span></code></pre> +</div> +</div> +<div class="paragraph"> +<p>1 行目を除き、先ほどのコードとほぼ同じものが出てきた。もう一度実行してみる。</p> +</div> +<div id="source." class="listingblock"> +<div class="content"> +<pre class="rouge highlight"><code data-lang="php"><span class="c1">#</span> +<span class="nc">W</span> +<span class="o"><?</span><span class="n">php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span> +<span class="cp"><?php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">""</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span></code></pre> +</div> +</div> +<div class="paragraph"> +<p>今度は 2 行目が書き換えられた。すべての行が変化するまで繰り返すと次のようになる。</p> +</div> +<div id="source." class="listingblock"> +<div class="content"> +<pre class="rouge highlight"><code data-lang="php"><span class="c1">#</span> +<span class="nc">W</span> +<span class="nc">E</span> +<span class="nc">L</span> +<span class="nc">O</span> +<span class="nc">V</span> +<span class="nc">E</span> +<span class="nc">P</span> +<span class="nc">H</span> +<span class="nc">P</span></code></pre> +</div> +</div> +<div class="paragraph"> +<p>トークン「#WELOVEPHP」が手に入った。</p> +</div> + </div> +</section> + + + + + +<section class="section-1"> + <h2 id="" class="section-header"> + + 解説 + + </h2> + <div class="section-body"> + <div class="paragraph"> +<p>一見すると同じ行が 10 行並んでいるだけなのにも関わらず、なぜそれぞれの行で出力が変わるのか。ソースコードをコピーして、適当なエディタに貼り付けるとわかりやすい。</p> +</div> +<div class="paragraph"> +<p>Vim で開くと次のようになる (1 行目を抜粋)。</p> +</div> +<div id="source." class="listingblock"> +<div class="content"> +<pre class="rouge highlight"><code data-lang="php"><span class="o"><?</span><span class="n">php</span> <span class="nb">printf</span><span class="p">((</span><span class="k">isset</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">?</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">trim</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span><span class="s2">"<200b>"</span><span class="p">)</span><span class="o">:</span><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">))(</span><span class="nv">$s</span><span class="o">=</span><span class="s1">'<200b><?php printf((isset($s)?fn($s)=>trim($s,"<200b>"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span class="p">)</span><span class="mf">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="s2">"</span><span class="se">\x27</span><span class="nv">$s</span><span class="se">\x27</span><span class="s2">"</span><span class="p">);</span><span class="cp">?></span></code></pre> +</div> +</div> +<div class="paragraph"> +<p><code><200b></code> と表示されているのは、Unicode の U+200b で、ゼロ幅スペースである。</p> +</div> +<div class="admonitionblock note"> +<table> +<tr> +<td class="icon"> +<div class="title">Note</div> +</td> +<td class="content"> +エディタによっては、ゼロ幅スペースが見えないことがある。VSCode ではブラウザと同様に不可視だった。 +</td> +</tr> +</table> +</div> +<div class="paragraph"> +<p>文字列リテラルの中にゼロ幅スペースを仕込むことで、見た目を変えずに情報をエンコードすることが可能となる。</p> +</div> +<div class="paragraph"> +<p>続いて、トークンへの変換ロジックを解析する。注目すべきはこの部分だ。以下、ゼロ幅スペースは Vim での表示に合わせて <code><200b></code> と記載する。</p> +</div> +<div id="source." class="listingblock"> +<div class="content"> +<pre class="rouge highlight"><code data-lang="php"><span class="k">fn</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">=></span><span class="nb">chr</span><span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$s</span><span class="p">)</span><span class="o">/</span><span class="mi">3</span><span class="p">)</span></code></pre> +</div> +</div> +<div class="paragraph"> +<p>PHP の <code>strlen()</code> は文字列のバイト数を返す。1 行目の <code>$s</code> は以下の内容となっており、</p> +</div> +<div id="source." class="listingblock"> +<div class="content"> +<pre class="rouge highlight"><code data-lang="php"><span class="nv">$s</span><span class="o">=</span><span class="s1">'<200b><?php printf((isset($s)?fn($s)=>trim($s,"<200b>"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span></code></pre> +</div> +</div> +<div class="paragraph"> +<p>このソースコードは UTF-8 で書かれているので、105 バイトになる。それを 3 で割ると 35 となり、これは <code>#</code> の ASCII コードと一致する。他の行も、同様にしてゼロ幅スペースを詰めることで文字列長を調整し、トークンをエンコードしている。</p> +</div> +<div class="paragraph"> +<p>デコード部以外の部分は、quine のための記述である。</p> +</div> + </div> +</section> + + + + + +<section class="section-1"> + <h2 id="" class="section-header"> + + おわりに + + </h2> + <div class="section-body"> + <div class="paragraph"> +<p><a href="https://blog.rust-lang.org/2021/11/01/cve-2021-42574.html">CVE-2021-42574</a> に着想を得た作品。この脆弱性は、Unicode の制御文字である left-to-right mark と right-to-left mark を利用し、ソースコードの実際の内容を欺く、というもの。簡単のためゼロ幅スペースを用いることとし、ついでに quine にもするとこうなった。</p> +</div> +<div class="paragraph"> +<p>ボツになった理由は、ゼロ幅スペースを表示してくるエディタが想像以上に多かったため。「同じ行が並んでいるだけなのに出力が異なる」というアイデアの根幹を崩されてしまうので、この問題は不採用となった。</p> +</div> + </div> +</section> + </div> + </article> + </main> + <footer class="footer"> + © 2021 nsfisis + </footer> + </body> +</html> diff --git a/public/posts/index.html b/public/posts/index.html index 029251b..1207acd 100644 --- a/public/posts/index.html +++ b/public/posts/index.html @@ -36,6 +36,22 @@ </header> <article class="post-entry"> + <a href="/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2/"> + <header class="entry-header"> + <h2>PHPerKaigi 2023: ボツになったトークン問題 その 2</h2> + </header> + <section class="entry-content"> + <p> + 来年の PHPerKaigi 2023 でデジタルサーカス株式会社から出題予定のトークン問題のうち、 ボツになった問題を公開する (その 2)。 + </p> + </section> + <footer class="entry-footer"> + Posted on <time datetime="2022-11-19">2022-11-19</time> + </footer> + </a> + </article> + + <article class="post-entry"> <a href="/posts/2022-10-28/setup-server-for-this-site/"> <header class="entry-header"> <h2>【備忘録】このサイト用の VPS をセットアップしたときのメモ</h2> diff --git a/public/tags/php/index.html b/public/tags/php/index.html index cd9a853..c20c486 100644 --- a/public/tags/php/index.html +++ b/public/tags/php/index.html @@ -36,6 +36,22 @@ </header> <article class="post-entry"> + <a href="/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2/"> + <header class="entry-header"> + <h2>PHPerKaigi 2023: ボツになったトークン問題 その 2</h2> + </header> + <section class="entry-content"> + <p> + 来年の PHPerKaigi 2023 でデジタルサーカス株式会社から出題予定のトークン問題のうち、 ボツになった問題を公開する (その 2)。 + </p> + </section> + <footer class="entry-footer"> + Posted on <time datetime="2022-11-19">2022-11-19</time> + </footer> + </a> + </article> + + <article class="post-entry"> <a href="/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/"> <header class="entry-header"> <h2>PHPerKaigi 2023: ボツになったトークン問題 その 1</h2> diff --git a/public/tags/phperkaigi/index.html b/public/tags/phperkaigi/index.html index e59c245..3a536bc 100644 --- a/public/tags/phperkaigi/index.html +++ b/public/tags/phperkaigi/index.html @@ -36,6 +36,22 @@ </header> <article class="post-entry"> + <a href="/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2/"> + <header class="entry-header"> + <h2>PHPerKaigi 2023: ボツになったトークン問題 その 2</h2> + </header> + <section class="entry-content"> + <p> + 来年の PHPerKaigi 2023 でデジタルサーカス株式会社から出題予定のトークン問題のうち、 ボツになった問題を公開する (その 2)。 + </p> + </section> + <footer class="entry-footer"> + Posted on <time datetime="2022-11-19">2022-11-19</time> + </footer> + </a> + </article> + + <article class="post-entry"> <a href="/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/"> <header class="entry-header"> <h2>PHPerKaigi 2023: ボツになったトークン問題 その 1</h2> |
