aboutsummaryrefslogtreecommitdiffhomepage
path: root/public/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3/index.html
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2023-03-15 02:20:00 +0900
committernsfisis <nsfisis@gmail.com>2023-03-16 14:05:15 +0900
commit7b6319986030fc8a2fb5f851a431b5113e774f60 (patch)
tree522cb3837707660373ddaf43da26bc2bf1dbc683 /public/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3/index.html
parentbfac7998b0f7abd8dbde016535037cf1d3174336 (diff)
downloadblog.nsfisis.dev-7b6319986030fc8a2fb5f851a431b5113e774f60.tar.gz
blog.nsfisis.dev-7b6319986030fc8a2fb5f851a431b5113e774f60.tar.zst
blog.nsfisis.dev-7b6319986030fc8a2fb5f851a431b5113e774f60.zip
fix(content): fix XML notations
Diffstat (limited to 'public/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3/index.html')
-rw-r--r--public/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3/index.html148
1 files changed, 74 insertions, 74 deletions
diff --git a/public/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3/index.html b/public/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3/index.html
index 6896530..a7f86b3 100644
--- a/public/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3/index.html
+++ b/public/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3/index.html
@@ -83,23 +83,23 @@
</p>
<pre class="highlight" language="php" linenumbering="unnumbered"><code>&lt;?php
- try {
- f(g() / __LINE__);
- } catch (Throwable $e) {
- while ($e = $e-&gt;getPrevious()) printf(&apos;%c&apos;, $e-&gt;getLine() + 23);
- echo &quot;\n&quot;;
- }
- function f(int $i) {
- if ($i &lt; 0) f();
- try {
+try {
+ f(g() / __LINE__);
+} catch (Throwable $e) {
+ while ($e = $e-&gt;getPrevious()) printf(&apos;%c&apos;, $e-&gt;getLine() + 23);
+ echo &quot;\n&quot;;
+}
+function f(int $i) {
+ if ($i &lt; 0) f();
+ try {
match ($i) {
- 0 =&gt; 0 / 0,
+ 0 =&gt; 0 / 0,
- 15, 36 =&gt; 0 / 0,
- 14 =&gt; 0 / 0,
- 37 =&gt; 0 / 0,
+ 15, 36 =&gt; 0 / 0,
+ 14 =&gt; 0 / 0,
+ 37 =&gt; 0 / 0,
@@ -110,16 +110,16 @@
- 6 =&gt; 0 / 0,
+ 6 =&gt; 0 / 0,
- 5 =&gt; 0 / 0,
+ 5 =&gt; 0 / 0,
- 22 =&gt; 0 / 0,
+ 22 =&gt; 0 / 0,
- 34, 35 =&gt; 0 / 0,
+ 34, 35 =&gt; 0 / 0,
@@ -128,10 +128,10 @@
- 25 =&gt; 0 / 0,
- 17, 21 =&gt; 0 / 0,
+ 25 =&gt; 0 / 0,
+ 17, 21 =&gt; 0 / 0,
- 24, 32 =&gt; 0 / 0,
+ 24, 32 =&gt; 0 / 0,
@@ -139,12 +139,12 @@
- 33 =&gt; 0 / 0,
+ 33 =&gt; 0 / 0,
- 16 =&gt; 0 / 0,
+ 16 =&gt; 0 / 0,
- 18 =&gt; 0 / 0,
+ 18 =&gt; 0 / 0,
@@ -153,37 +153,37 @@
- 7 =&gt; 0 / 0,
+ 7 =&gt; 0 / 0,
- 2 =&gt; 0 / 0,
- 1, 20 =&gt; 0 / 0,
- 10, 28 =&gt; 0 / 0,
- 8, 12, 26 =&gt; 0 / 0,
- 4, 9, 13 =&gt; 0 / 0,
+ 2 =&gt; 0 / 0,
+ 1, 20 =&gt; 0 / 0,
+ 10, 28 =&gt; 0 / 0,
+ 8, 12, 26 =&gt; 0 / 0,
+ 4, 9, 13 =&gt; 0 / 0,
- 31 =&gt; 0 / 0,
+ 31 =&gt; 0 / 0,
- 29 =&gt; 0 / 0,
+ 29 =&gt; 0 / 0,
- 11 =&gt; 0 / 0,
+ 11 =&gt; 0 / 0,
- 3, 19, 23 =&gt; 0 / 0,
+ 3, 19, 23 =&gt; 0 / 0,
- 27 =&gt; 0 / 0,
+ 27 =&gt; 0 / 0,
- 30 =&gt; 0 / 0,
+ 30 =&gt; 0 / 0,
};
- } finally {
+ } finally {
f($i - 1);
- }
- }
+ }
+}
@@ -191,9 +191,9 @@
- function g() {
- return __LINE__;
- }</code></pre>
+function g() {
+ return __LINE__;
+}</code></pre>
<p>
&quot;Catchline&quot; と名付けた作品。実行するとトークン<code>#base64_decode(&apos;SGVsbG8sIFdvcmxkIQ==&apos;)</code>が得られる。
@@ -239,18 +239,18 @@
<pre class="highlight" language="php" linenumbering="unnumbered"><code>&lt;?php
- try {
- try {
- throw new Exception(&quot;Error 1&quot;);
- } finally {
- throw new Exception(&quot;Error 2&quot;);
- }
- } catch (Exception $e) {
- echo $e-&gt;getMessage() . PHP_EOL;
- // =&gt; Error 2
- echo $e-&gt;getPrevious()-&gt;getMessage() . PHP_EOL;
- // =&gt; Error 1
- }</code></pre>
+try {
+ try {
+ throw new Exception(&quot;Error 1&quot;);
+ } finally {
+ throw new Exception(&quot;Error 2&quot;);
+ }
+} catch (Exception $e) {
+ echo $e-&gt;getMessage() . PHP_EOL;
+ // =&gt; Error 2
+ echo $e-&gt;getPrevious()-&gt;getMessage() . PHP_EOL;
+ // =&gt; Error 1
+}</code></pre>
<p>
この知識を元に、トークンの出力部を解析してみる。
@@ -264,14 +264,14 @@
</p>
<pre class="highlight" language="php" linenumbering="unnumbered"><code>&lt;?php
- try {
- f(g() / __LINE__);
- } catch (Throwable $e) {
- while ($e = $e-&gt;getPrevious()) {
- printf(&apos;%c&apos;, $e-&gt;getLine() + 23);
- }
- echo &quot;\n&quot;;
- }</code></pre>
+try {
+ f(g() / __LINE__);
+} catch (Throwable $e) {
+ while ($e = $e-&gt;getPrevious()) {
+ printf(&apos;%c&apos;, $e-&gt;getLine() + 23);
+ }
+ echo &quot;\n&quot;;
+}</code></pre>
<p>
出力をおこなう<code>catch</code>節を見てみると、<code>Throwable::getPrevious()</code>を呼び出してエラーチェインを辿り、<code>Throwable::getLine()</code>でエラーが発生した行数を取得している。その行数に<code>23</code>なるマジックナンバーを足し、フォーマット指定子<code>%c</code>で出力している。
@@ -281,7 +281,7 @@
フォーマット指定子<code>%c</code>は、整数を ASCII コード<span></span>と見做して印字する。トークン<code>#base64_decode(&apos;SGVsbG8sIFdvcmxkIQ==&apos;)</code>の<code>b</code>であれば、ASCII コード<code>98</code>なので、75 行目で発生したエラー、
</p>
- <pre class="highlight" language="php" linenumbering="unnumbered"><code> 1, 20 =&gt; 0 / 0,</code></pre>
+ <pre class="highlight" language="php" linenumbering="unnumbered"><code>1, 20 =&gt; 0 / 0,</code></pre>
<p>
によって表現されている。エラーを起こす方法はいろいろと考えられるが、今回はゼロ除算を使った。
@@ -299,9 +299,9 @@
</p>
<pre class="highlight" language="php" linenumbering="unnumbered"><code>function f(int $i) {
- if ($i &lt; 0) f();
- try {
- match ($i) {
+ if ($i &lt; 0) f();
+ try {
+ match ($i) {
0 =&gt; 0 / 0, // 12 行目
@@ -313,23 +313,23 @@
// (略)
30 =&gt; 0 / 0, // 97 行目
- };
- } finally {
- f($i - 1);
- }
- }</code></pre>
+ };
+ } finally {
+ f($i - 1);
+ }
+}</code></pre>
<p>
前述のように、<code>finally</code>節でエラーを投げると PHP 処理系が<code>$previous</code>を設定する。ここでは、エラーを繋げるために<code>f()</code>を再帰呼び出ししている。最初に<code>f()</code>を呼び出している箇所を確認すると、
</p>
<pre class="highlight" language="php" linenumbering="unnumbered"><code>&lt;?php
- try {
- f(g() / __LINE__); // 3 行目</code></pre>
+try {
+ f(g() / __LINE__); // 3 行目</code></pre>
<pre class="highlight" language="php" linenumbering="unnumbered"><code>function g() {
- return __LINE__; // 111 行目
- }</code></pre>
+ return __LINE__; // 111 行目
+}</code></pre>
<p>
<code>f()</code>には<code>111 / 3</code>で<code>37</code>が渡されることがわかる。そこから 1 ずつ減らして再帰呼び出ししていき、0 より小さくなったら<code>f()</code>を引数なしで呼び出す。引数の数が足りないと呼び出しに失敗するので、再帰はここで止まる。