summaryrefslogtreecommitdiffhomepage
path: root/vhosts/blog/content/posts/2022-11-19
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2023-09-20 19:56:52 +0900
committernsfisis <nsfisis@gmail.com>2023-09-20 19:56:57 +0900
commita84908b7e8a0e2423afd6b836eccf27a420270b4 (patch)
tree00204b62358f8c57fcb36f601db360626484cc1a /vhosts/blog/content/posts/2022-11-19
parent0b488f85380f964c40b0b9aae69c6611bc7978bc (diff)
downloadnsfisis.dev-a84908b7e8a0e2423afd6b836eccf27a420270b4.tar.gz
nsfisis.dev-a84908b7e8a0e2423afd6b836eccf27a420270b4.tar.zst
nsfisis.dev-a84908b7e8a0e2423afd6b836eccf27a420270b4.zip
feat(blog/nuldoc): change content format from DocBook to NulDoc
Diffstat (limited to 'vhosts/blog/content/posts/2022-11-19')
-rw-r--r--vhosts/blog/content/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2.ndoc (renamed from vhosts/blog/content/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2.xml)186
1 files changed, 91 insertions, 95 deletions
diff --git a/vhosts/blog/content/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2.xml b/vhosts/blog/content/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2.ndoc
index 0332179d..541a0c19 100644
--- a/vhosts/blog/content/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2.xml
+++ b/vhosts/blog/content/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2.ndoc
@@ -1,46 +1,42 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<article xmlns="http://docbook.org/ns/docbook" xmlns:xl="http://www.w3.org/1999/xlink" version="5.0">
- <info>
- <title>PHPerKaigi 2023: ボツになったトークン問題 その 2</title>
- <abstract>
- 来年の PHPerKaigi 2023 でデジタルサーカス株式会社から出題予定のトークン問題のうち、ボツになった問題を公開する (その 2)。
- </abstract>
- <keywordset>
- <keyword>php</keyword>
- <keyword>phperkaigi</keyword>
- </keywordset>
- <revhistory>
- <revision>
- <date>2022-11-19</date>
- <revremark>公開</revremark>
- </revision>
- </revhistory>
- </info>
- <section xml:id="intro">
- <title>はじめに</title>
- <para>
- 2023 年 3 月 23 日から 25 日にかけて開催予定 (記事執筆時点) の <link xl:href="https://phperkaigi.jp/2023/">PHPerKaigi 2023</link> において、
- 昨年と同様に、弊社 <link xl:href="https://www.dgcircus.com/">デジタルサーカス株式会社</link> からトークン問題を出題予定である。
- </para>
- <para>
- 昨年のトークン問題の記事はこちら: <link xl:href="/posts/2022-04-09/phperkaigi-2022-tokens/">PHPerKaigi 2022 トークン問題の解説</link>
- </para>
- <para>
+---
+[article]
+title = "PHPerKaigi 2023: ボツになったトークン問題 その 2"
+description = "来年の PHPerKaigi 2023 でデジタルサーカス株式会社から出題予定のトークン問題のうち、ボツになった問題を公開する (その 2)。"
+tags = [
+ "php",
+ "phperkaigi",
+]
+
+[[article.revisions]]
+date = "2022-11-19"
+remark = "公開"
+---
+<article>
+ <section id="intro">
+ <h>はじめに</h>
+ <p>
+ 2023 年 3 月 23 日から 25 日にかけて開催予定 (記事執筆時点) の <a href="https://phperkaigi.jp/2023/">PHPerKaigi 2023</a> において、
+ 昨年と同様に、弊社 <a href="https://www.dgcircus.com/">デジタルサーカス株式会社</a> からトークン問題を出題予定である。
+ </p>
+ <p>
+ 昨年のトークン問題の記事はこちら: <a href="/posts/2022-04-09/phperkaigi-2022-tokens/">PHPerKaigi 2022 トークン問題の解説</a>
+ </p>
+ <p>
すでに 2023 年用の問題は作成済みであるが、その制作過程の中でいくつかボツ問ができた。せっかくなので、PHPerKaigi 開催を待つ間に紹介しようと思う。
- </para>
- <para>
+ </p>
+ <p>
10 月から 2 月まで、毎月 1 記事ずつ公開していく予定 (忘れていなければ)。
- </para>
- <para>
- その 1 はこちら: <link xl:href="/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/">PHPerKaigi 2023: ボツになったトークン問題 その 1</link>
- </para>
+ </p>
+ <p>
+ その 1 はこちら: <a href="/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/">PHPerKaigi 2023: ボツになったトークン問題 その 1</a>
+ </p>
</section>
- <section xml:id="quiz">
- <title>問題</title>
- <para>
+ <section id="quiz">
+ <h>問題</h>
+ <p>
注意: これはボツ問なので、得られたトークンを PHPerKaigi で入力してもポイントにはならない。
- </para>
- <programlisting language="php" linenumbering="unnumbered">
+ </p>
+ <codeblock language="php">
<![CDATA[
<?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");?>
@@ -53,17 +49,17 @@
<?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");?>
]]>
- </programlisting>
- <para>
+ </codeblock>
+ <p>
"And Then There Were None" (そして誰もいなくなった) と名付けた作品。変則 quine (自分自身と同じソースコードを出力するプログラム) になっている。
- </para>
+ </p>
</section>
- <section xml:id="how-to-obtain-token">
- <title>トークン入手方法</title>
- <para>
+ <section id="how-to-obtain-token">
+ <h>トークン入手方法</h>
+ <p>
実行してみると、次のような出力が得られる。
- </para>
- <programlisting language="php" linenumbering="unnumbered">
+ </p>
+ <codeblock language="php">
<![CDATA[
#
<?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");?>
@@ -76,11 +72,11 @@
<?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");?>
]]>
- </programlisting>
- <para>
+ </codeblock>
+ <p>
1 行目を除き、先ほどのコードとほぼ同じものが出てきた。もう一度実行してみる。
- </para>
- <programlisting language="php" linenumbering="unnumbered">
+ </p>
+ <codeblock language="php">
<![CDATA[
#
W
@@ -93,11 +89,11 @@
<?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");?>
]]>
- </programlisting>
- <para>
+ </codeblock>
+ <p>
今度は 2 行目が書き換えられた。すべての行が変化するまで繰り返すと次のようになる。
- </para>
- <programlisting language="php" linenumbering="unnumbered">
+ </p>
+ <codeblock language="php">
<![CDATA[
#
W
@@ -110,65 +106,65 @@
H
P
]]>
- </programlisting>
- <para>
+ </codeblock>
+ <p>
トークン「#WELOVEPHP」が手に入った。
- </para>
+ </p>
</section>
- <section xml:id="commentary">
- <title>解説</title>
- <para>
+ <section id="commentary">
+ <h>解説</h>
+ <p>
一見すると同じ行が 10 行並んでいるだけなのにも関わらず、なぜそれぞれの行で出力が変わるのか。ソースコードをコピーして、適当なエディタに貼り付けるとわかりやすい。
- </para>
- <para>
+ </p>
+ <p>
Vim で開くと次のようになる (1 行目を抜粋)。
- </para>
- <programlisting language="php" linenumbering="unnumbered">
+ </p>
+ <codeblock language="php">
<![CDATA[
<?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");?>
]]>
- </programlisting>
- <para>
- <literal>&lt;200b&gt;</literal> と表示されているのは、Unicode の U+200b で、ゼロ幅スペースである。
- </para>
+ </codeblock>
+ <p>
+ <code>&lt;200b&gt;</code> と表示されているのは、Unicode の U+200b で、ゼロ幅スペースである。
+ </p>
<note>
- <para>
+ <p>
エディタによっては、ゼロ幅スペースが見えないことがある。VSCode ではブラウザと同様に不可視だった。
- </para>
+ </p>
</note>
- <para>
+ <p>
文字列リテラルの中にゼロ幅スペースを仕込むことで、見た目を変えずに情報をエンコードすることが可能となる。
- </para>
- <para>
- 続いて、トークンへの変換ロジックを解析する。注目すべきはこの部分だ。以下、ゼロ幅スペースは Vim での表示に合わせて <literal>&lt;200b&gt;</literal> と記載する。
- </para>
- <programlisting language="php" linenumbering="unnumbered">
+ </p>
+ <p>
+ 続いて、トークンへの変換ロジックを解析する。注目すべきはこの部分だ。以下、ゼロ幅スペースは Vim での表示に合わせて <code>&lt;200b&gt;</code> と記載する。
+ </p>
+ <codeblock language="php">
<![CDATA[
fn($s)=>chr(strlen($s)/3)
]]>
- </programlisting>
- <para>
- PHP の <literal>strlen()</literal> は文字列のバイト数を返す。1 行目の <literal>$s</literal> は以下の内容となっており、
- </para>
- <programlisting language="php" linenumbering="unnumbered">
+ </codeblock>
+ <p>
+ PHP の <code>strlen()</code> は文字列のバイト数を返す。1 行目の <code>$s</code> は以下の内容となっており、
+ </p>
+ <codeblock language="php">
<![CDATA[
$s='<200b><?php printf((isset($s)?fn($s)=>trim($s,"<200b>"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'
]]>
- </programlisting>
- <para>
- このソースコードは UTF-8 で書かれているので、105 バイトになる。それを 3 で割ると 35 となり、これは <literal>#</literal> の ASCII コードと一致する。他の行も、同様にしてゼロ幅スペースを詰めることで文字列長を調整し、トークンをエンコードしている。
- </para>
- <para>
+ </codeblock>
+ <p>
+ このソースコードは UTF-8 で書かれているので、105 バイトになる。それを 3 で割ると 35 となり、これは <code>#</code> の ASCII コードと一致する。他の行も、同様にしてゼロ幅スペースを詰めることで文字列長を調整し、トークンをエンコードしている。
+ </p>
+ <p>
デコード部以外の部分は、quine のための記述である。
- </para>
+ </p>
</section>
- <section xml:id="outro">
- <title>おわりに</title>
- <para>
- <link xl:href="https://blog.rust-lang.org/2021/11/01/cve-2021-42574.html">CVE-2021-42574</link> に着想を得た作品。この脆弱性は、Unicode の制御文字である left-to-right mark と right-to-left mark を利用し、ソースコードの実際の内容を欺く、というもの。簡単のためゼロ幅スペースを用いることとし、ついでに quine にもするとこうなった。
- </para>
- <para>
+ <section id="outro">
+ <h>おわりに</h>
+ <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>
+ <p>
ボツになった理由は、ゼロ幅スペースを表示してくるエディタが想像以上に多かったため。「同じ行が並んでいるだけなのに出力が異なる」というアイデアの根幹を崩されてしまうので、この問題は不採用となった。
- </para>
+ </p>
</section>
</article>