From 98682c7a8792e7e79e487fea5024d25cee5aa310 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Wed, 15 Mar 2023 01:36:13 +0900 Subject: fix(nuldoc):
 contained unnecessary whitespaces inside it

---
 .../2022-04-09/phperkaigi-2022-tokens/index.html   | 76 +++++++---------------
 1 file changed, 23 insertions(+), 53 deletions(-)

(limited to 'public/posts/2022-04-09/phperkaigi-2022-tokens')

diff --git a/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html b/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html
index d16739b..bbeacb2 100644
--- a/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html
+++ b/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html
@@ -66,8 +66,7 @@
               ソースコードはこちら。実行には PHP 8.1 以上が必要なので注意。
             

-
-              <?php
+            
<?php
 
   declare(strict_types=0O1);
 
@@ -135,8 +134,7 @@
   $👉, $👍, $👍, $📝,
   $👉, $👎, $📝,
   $👈, $📝,
-  ]);
-            
+ ]);

この問題は、単に適切なバージョンの PHP で動かせばトークンが得られる。 @@ -165,8 +163,7 @@ なお、brainf*ck プログラムを普通の書き方で書くと、次のようになる。

-
-                  + + + + + + + + + +
+                
+ + + + + + + + + +
 [
 > + + +
 > + + + + +
@@ -187,8 +184,7 @@
 < .
 > + + .
 > - .
-< .
-                
+< .

実行結果はこちら:https://ideone.com/22VWmb @@ -271,9 +267,7 @@ ソースコードのライセンスを示したこの部分だが、

-
-                  https://creativecommons.org/publicdomain/zero/1.0/
-                
+
https://creativecommons.org/publicdomain/zero/1.0/

完全に合法な PHP のコードである。https:部分はラベル、//以降は行コメントになっている。 @@ -286,13 +280,11 @@ ソースコード中に、ほとんど数値リテラルが書かれていないことにお気づきだろうか。 PHP では、型変換を利用することで任意の整数を作り出すことができる。

-
-                  assert(0 === +!![]);
+                
assert(0 === +!![]);
 assert(1 === +![]);
 assert(2 === ![]+![]);
 assert(3 === ![]+![]+![]);
-assert(10 === +(![].+!![]));
-                
+assert(10 === +(![].+!![]));

[]!を適用するとtrueが返ってくる。それに+を適用すると、boolからintヘの型変換が走り、1が生成される。10はさらにトリッキーだ。まず10を作り、.で文字列として結合する ('10')。これに+を適用すると、stringからintへの型変換が走り、10が生まれる (コード量に頓着しないなら、1を 10 個足し合わせてももちろん 10 が作れる)。 @@ -333,8 +325,7 @@ assert(10 === +(![].+!![])); ソースコードはこちら。実行には PHP 8.0 以上が必要なので注意。

-
-              <?php
+            
<?php
 
   /*********************************************************
   * This program displays a PHPer token.                  *
@@ -367,8 +358,7 @@ assert(10 === +(![].+!![]));
   $x = str_replace(search: ['0', '1'], replace: [' ', '#'], subject: $x);
   $x = implode("\n", str_split($x, length: 5));
   echo "{$x}\n\n";
-  }
-            
+ }

さて、この問題はさきほどのように単純に実行しただけでは、謎のブロックが表示されるだけでトークンは得られない。 トークンを得るためには、ソースコードを読み、定数Nを特定する必要がある。 @@ -384,43 +374,33 @@ assert(10 === +(![].+!![])); まずはソースコードを読んでいく。

-
-                $token = [
+              
$token = [
   // 略
-  ];
-              
+ ];

数値からなる$tokenがあり、各要素をループしている。

-
-                  $x = $x ^ N;
-              
+
  $x = $x ^ N;

まずは排他的論理和 (xor) を取り、

-
-                  $x = sprintf('%025b', $x);
-              
+
  $x = sprintf('%025b', $x);

二進数に変換して、

-
-                  $x = str_replace(search: ['0', '1'], replace: [' ', '#'], subject: $x);
-              
+
  $x = str_replace(search: ['0', '1'], replace: [' ', '#'], subject: $x);

0 を空白に、1 を#にし、

-
-                  $x = implode("\n", str_split($x, length: 5));
-              
+
  $x = implode("\n", str_split($x, length: 5));

5文字ごとに区切ったあと、改行で結合している。 @@ -474,16 +454,13 @@ assert(10 === +(![].+!![])); Nは高々

-
-                assert(0 <= N && N <= 0b11111_11111_11111_11111_11111);
-              
+
assert(0 <= N && N <= 0b11111_11111_11111_11111_11111);

なのでブルートフォースしてもよいが、ここではブルートフォースしない方法を紹介する。

-
-                <?php
+              
<?php
 
   $x = 0x14B499C;
 
@@ -498,15 +475,13 @@ assert(10 === +(![].+!![]));
   "#####\n" .
   " # # \n" .
   "#####\n" .
-  " # # ");
-              
+ " # # ");

この一連の変換に対する逆変換を考えると、次のようになる。

-
-                <?php
+              
<?php
 
 $x =
 " # # \n" .
@@ -521,8 +496,7 @@ $x = bindec($x);
 
 $n = $x ^ 0x14B499C;
 
-echo "N = $n\n";
-              
+echo "N = $n\n";

これを実行すると、Nが得られる。 @@ -536,8 +510,7 @@ echo "N = $n\n"; ソースコードはこちら。

-
-              <?php
+            
<?php
 
   // License: https://creativecommons.org/publicdomain/zero/1.0/
   // This is a quine-like program to generate a PHPer token.
@@ -565,16 +538,13 @@ echo "N = $n\n";
   $t = null.false; for ($i = 0; $i <= intdiv(__LINE__-035,6); ++$i) if (!isset($xs[$i])) break; else
   $t .= implode("\n", str_split(str_replace(['0','1'], ['  ','##'], sprintf(chr(37) . '025b', $xs[$i])), 012)) . "\n\n";
   $ws = array_map(fn($w) => implode(', ', $w), array_chunk(array_map(fn($x) => sprintf('0x' . chr(37) . '07X', $x), $xs), 10));
-  printf($s, $t, str_rot13("<<<'D'\n{$s}\nD"), implode(",\n", $ws));
-            
+ printf($s, $t, str_rot13("<<<'D'\n{$s}\nD"), implode(",\n", $ws));

コメントにもあるとおり、次のようにして実行すれば答えがでてくる。

-
-              $ php toquine.php | php | php | php | ...
-            
+
$ php toquine.php | php | php | php | ...

実際にはもう少しパイプで繋げなければならない。 -- cgit v1.2.3-70-g09d2