From 7b6319986030fc8a2fb5f851a431b5113e774f60 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Wed, 15 Mar 2023 02:20:00 +0900 Subject: fix(content): fix XML notations --- .../phperkaigi-2023-unused-token-quiz-3/index.html | 148 ++++++++++----------- 1 file changed, 74 insertions(+), 74 deletions(-) (limited to 'public/posts/2023-01-10') 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 @@

<?php
-    try {
-    f(g() / __LINE__);
-    } catch (Throwable $e) {
-    while ($e = $e->getPrevious()) printf('%c', $e->getLine() + 23);
-    echo "\n";
-    }
-    function f(int $i) {
-    if ($i < 0) f();
-    try {
+try {
+  f(g() / __LINE__);
+} catch (Throwable $e) {
+  while ($e = $e->getPrevious()) printf('%c', $e->getLine() + 23);
+  echo "\n";
+}
+function f(int $i) {
+  if ($i < 0) f();
+  try {
     match ($i) {
-    0 => 0 / 0,
+      0 => 0 / 0,
 
 
 
-    15, 36 => 0 / 0,
-    14 => 0 / 0,
-    37 => 0 / 0,
+      15, 36 => 0 / 0,
+      14 => 0 / 0,
+      37 => 0 / 0,
 
 
 
@@ -110,16 +110,16 @@
 
 
 
-    6 => 0 / 0,
+      6 => 0 / 0,
 
-    5 => 0 / 0,
+      5 => 0 / 0,
 
-    22 => 0 / 0,
+      22 => 0 / 0,
 
 
 
 
-    34, 35 => 0 / 0,
+      34, 35 => 0 / 0,
 
 
 
@@ -128,10 +128,10 @@
 
 
 
-    25 => 0 / 0,
-    17, 21 => 0 / 0,
+      25 => 0 / 0,
+      17, 21 => 0 / 0,
 
-    24, 32 => 0 / 0,
+      24, 32 => 0 / 0,
 
 
 
@@ -139,12 +139,12 @@
 
 
 
-    33 => 0 / 0,
+      33 => 0 / 0,
 
-    16 => 0 / 0,
+      16 => 0 / 0,
 
 
-    18 => 0 / 0,
+      18 => 0 / 0,
 
 
 
@@ -153,37 +153,37 @@
 
 
 
-    7 => 0 / 0,
+      7 => 0 / 0,
 
-    2 => 0 / 0,
-    1, 20 => 0 / 0,
-    10, 28 => 0 / 0,
-    8, 12, 26 => 0 / 0,
-    4, 9, 13 => 0 / 0,
+      2 => 0 / 0,
+      1, 20 => 0 / 0,
+      10, 28 => 0 / 0,
+      8, 12, 26 => 0 / 0,
+      4, 9, 13 => 0 / 0,
 
 
 
 
 
-    31 => 0 / 0,
+      31 => 0 / 0,
 
-    29 => 0 / 0,
+      29 => 0 / 0,
 
-    11 => 0 / 0,
+      11 => 0 / 0,
 
 
 
-    3, 19, 23 => 0 / 0,
+      3, 19, 23 => 0 / 0,
 
 
-    27 => 0 / 0,
+      27 => 0 / 0,
 
-    30 => 0 / 0,
+      30 => 0 / 0,
     };
-    } finally {
+  } finally {
     f($i - 1);
-    }
-    }
+  }
+}
 
 
 
@@ -191,9 +191,9 @@
 
 
 
-    function g() {
-    return __LINE__;
-      }
+function g() { + return __LINE__; +}

"Catchline" と名付けた作品。実行するとトークン#base64_decode('SGVsbG8sIFdvcmxkIQ==')が得られる。 @@ -239,18 +239,18 @@

<?php
 
-      try {
-      try {
-      throw new Exception("Error 1");
-      } finally {
-      throw new Exception("Error 2");
-      }
-      } catch (Exception $e) {
-      echo $e->getMessage() . PHP_EOL;
-      // => Error 2
-      echo $e->getPrevious()->getMessage() . PHP_EOL;
-      // => Error 1
-        }
+try { + try { + throw new Exception("Error 1"); + } finally { + throw new Exception("Error 2"); + } +} catch (Exception $e) { + echo $e->getMessage() . PHP_EOL; + // => Error 2 + echo $e->getPrevious()->getMessage() . PHP_EOL; + // => Error 1 +}

この知識を元に、トークンの出力部を解析してみる。 @@ -264,14 +264,14 @@

<?php
-      try {
-      f(g() / __LINE__);
-      } catch (Throwable $e) {
-      while ($e = $e->getPrevious()) {
-      printf('%c', $e->getLine() + 23);
-      }
-      echo "\n";
-        }
+try { + f(g() / __LINE__); +} catch (Throwable $e) { + while ($e = $e->getPrevious()) { + printf('%c', $e->getLine() + 23); + } + echo "\n"; +}

出力をおこなうcatch節を見てみると、Throwable::getPrevious()を呼び出してエラーチェインを辿り、Throwable::getLine()でエラーが発生した行数を取得している。その行数に23なるマジックナンバーを足し、フォーマット指定子%cで出力している。 @@ -281,7 +281,7 @@ フォーマット指定子%cは、整数を ASCII コードと見做して印字する。トークン#base64_decode('SGVsbG8sIFdvcmxkIQ==')bであれば、ASCII コード98なので、75 行目で発生したエラー、

-
      1, 20 => 0 / 0,
+
1, 20 => 0 / 0,

によって表現されている。エラーを起こす方法はいろいろと考えられるが、今回はゼロ除算を使った。 @@ -299,9 +299,9 @@

function f(int $i) {
-      if ($i < 0) f();
-      try {
-      match ($i) {
+  if ($i < 0) f();
+  try {
+    match ($i) {
       0 => 0 / 0, // 12 行目
 
 
@@ -313,23 +313,23 @@
       // (略)
 
       30 => 0 / 0, // 97 行目
-      };
-      } finally {
-      f($i - 1);
-      }
-        }
+ }; + } finally { + f($i - 1); + } +}

前述のように、finally節でエラーを投げると PHP 処理系が$previousを設定する。ここでは、エラーを繋げるためにf()を再帰呼び出ししている。最初にf()を呼び出している箇所を確認すると、

<?php
-      try {
-        f(g() / __LINE__); // 3 行目
+try { + f(g() / __LINE__); // 3 行目
function g() {
-      return __LINE__; // 111 行目
-        }
+ return __LINE__; // 111 行目 +}

f()には111 / 337が渡されることがわかる。そこから 1 ずつ減らして再帰呼び出ししていき、0 より小さくなったらf()を引数なしで呼び出す。引数の数が足りないと呼び出しに失敗するので、再帰はここで止まる。 -- cgit v1.2.3-70-g09d2