From de13d68cddef5bb321469bcffb868f27ddd5390e Mon Sep 17 00:00:00 2001
From: nsfisis
+
#include <iostream>
[[alignas]] [[alignof]] [[and]] [[and_eq]] [[asm]] [[auto]] [[bitand]]
@@ -126,7 +126,7 @@ std::cout << "Hello, World!" << std::endl;
上のコードでは[[using]]をコメントアウトしているが、これはusingキーワードのみ属性構文の中で意味を持つからであり、このコメントアウトを外すとコンパイルに失敗する。
-
+
// using の例
[[using foo: attr1, attr2]] int x; // [[foo::attr1, foo::attr2]] の糖衣構文
diff --git a/public/posts/2021-10-02/python-unbound-local-error/index.html b/public/posts/2021-10-02/python-unbound-local-error/index.html
index fa0b1db..27c2d05 100644
--- a/public/posts/2021-10-02/python-unbound-local-error/index.html
+++ b/public/posts/2021-10-02/python-unbound-local-error/index.html
@@ -60,7 +60,7 @@
Python でクロージャを作ろうと、次のようなコードを書いた。
-
+
def f():
x = 0
def g():
@@ -84,7 +84,7 @@ f()
local変数xが代入前に参照された、とある。これは、fのxを参照するのではなく、新しく別の変数をg内に作ってしまっているため。 前述のコードを宣言と代入を便宜上分けて書き直すと次のようになる。varを変数宣言のための構文として擬似的に利用している。
-
+
# 注: var は正しい Python の文法ではない。上記参照のこと
def f():
var x # f の local変数 'x' を宣言
@@ -101,7 +101,7 @@ g()
当初の意図を表現するには、次のように書けばよい。
-
+
def f():
x = 0
def g():
diff --git a/public/posts/2021-10-02/ruby-detect-running-implementation/index.html b/public/posts/2021-10-02/ruby-detect-running-implementation/index.html
index 08700c4..ed7ccd5 100644
--- a/public/posts/2021-10-02/ruby-detect-running-implementation/index.html
+++ b/public/posts/2021-10-02/ruby-detect-running-implementation/index.html
@@ -65,7 +65,7 @@
上記ページの例から引用する:
-
+
$ ruby-1.9.1 -ve 'p RUBY_ENGINE'
ruby 1.9.1p0 (2009-03-04 revision 22762) [x86_64-linux]
"ruby"
@@ -192,7 +192,7 @@ jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-03-16 rev 9419) [i386-java]
mruby 該当部分のソースより引用:
-
+
/*
* Ruby engine.
*/
diff --git a/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html b/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html
index 1def6b6..9b1df47 100644
--- a/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html
+++ b/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html
@@ -65,7 +65,7 @@
使われることは稀だが、Ruby ではthenがキーワードになっている。次のように使う:
-
+
if cond then
puts "Y"
else
@@ -77,7 +77,7 @@
このキーワードが現れうる場所はいくつかあり、if、unless、rescue、case構文がそれに当たる。 上記のように、何か条件を書いた後thenを置き、式がそこで終了していることを示すマーカーとして機能する。
-
+
# Example:
if x then
@@ -107,7 +107,7 @@ end
普通 Ruby のコードでthenを書くことはない。なぜか。次のコードを実行してみるとわかる。
-
+
if true puts 'Hello, World!' end
@@ -115,7 +115,7 @@ end
次のような構文エラーが出力される。
-
+
20:1: syntax error, unexpected local variable or method, expecting `then' or ';' or '\n'
if true puts 'Hello, World!' end
^~~~
@@ -131,7 +131,7 @@ end
ポイントは改行がthen(や;) の代わりとなることである。trueの後に改行を入れてみる。
-
+
if true
puts 'Hello, World!' end
@@ -147,7 +147,7 @@ puts 'Hello, World!' end
なぜthenや;や改行 (以下 「then等」) が必要なのだろうか。次の例を見てほしい:
-
+
if a b end
@@ -155,14 +155,14 @@ puts 'Hello, World!' end
thenも;も改行もないのでエラーになるが、これは条件式がどこまで続いているのかわからないためだ。 この例は二通りに解釈できる。
-
+
# a という変数かメソッドの評価結果が truthy なら b という変数かメソッドを評価
if a then
b
end
-
+
# a というメソッドに b という変数かメソッドの評価結果を渡して呼び出し、
# その結果が truthy なら何もしない
if a(b) then
@@ -188,7 +188,7 @@ end
https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986
-
+
p_case_body : keyword_in
{
SET_LEX_STATE(EXPR_BEG|EXPR_LABEL);
@@ -221,7 +221,7 @@ end
簡略版:
-
+
p_case_body : keyword_in p_top_expr then compstmt p_cases
;
@@ -234,7 +234,7 @@ end
これにより、case-whenによる従来の構文と同じように、then等をパターンの後ろに挿入すればよいことがわかった。つまり次の3通りのいずれかになる:
-
+
case x
in 1 then a
in 2 then b
@@ -261,7 +261,7 @@ end
ところで、p_top_exprにはifによる guard clause が書けるので、その場合はif-thenと似たような見た目になる。
-
+
case x
in 0 then a
in n if n < 0 then b
diff --git a/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html b/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html
index 8879a79..8bcb923 100644
--- a/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html
+++ b/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html
@@ -55,7 +55,7 @@
Rust において、プリミティブ型の名前は予約語でない。したがって、次のコードは合法である。
-
+
#![allow(non_camel_case_types)]
#![allow(dead_code)]
@@ -111,7 +111,7 @@ struct str;
rustcはセルフホストされている (=rustc自身が Rust で書かれている) ので、boolやcharなどで適当に検索をかけてもノイズが多すぎて話にならない。 しかし、お誂え向きなことにi128/u128というコンパイラ自身が使うことがなさそうな型が存在するのでこれを使ってgit grepしてみる。
-
+
$ git grep "\bi128\b" | wc # i128
165 1069 15790
@@ -126,7 +126,7 @@ $ git grep "\bbool\b" | wc # cf. bool の結果
165 程度であれば探すことができそうだ。今回は、クレート名を見ておおよその当たりをつけた。
-
+
$ git grep "\bi128\b"
...
rustc_resolve/src/lib.rs: table.insert(sym::i128, Int(IntTy::I128));
@@ -137,7 +137,7 @@ rustc_resolve/src/lib.rs: table.insert(sym::i128, Int(IntTy::I128));
rustc_resolveというのはいかにも名前解決を担いそうなクレート名である。該当箇所を見てみる。
-
+
/// Interns the names of the primitive types.
///
/// All other types are defined somewhere and possibly imported, but the primitive ones need
@@ -186,7 +186,7 @@ Self { primitive_types: table }
とある。次はこの struct の使用箇所を追う。追うと言っても使われている箇所は次の一箇所しかない。なお説明に不要な箇所は大きく削っている。
-
+
/// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
/// (略)
fn resolve_ident_in_lexical_scope(
@@ -226,7 +226,7 @@ None
動作がわかったところで、例として次のコードを考える。
-
+
#![allow(non_camel_case_types)]
struct bool;
diff --git a/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html b/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html
index 5fc12fc..db28b1c 100644
--- a/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html
+++ b/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html
@@ -112,7 +112,7 @@
https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86
-
+
{"BufAdd", EVENT_BUFADD},
{"BufCreate", EVENT_BUFADD},
@@ -121,7 +121,7 @@
https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97
-
+
{"BufRead", EVENT_BUFREADPOST},
{"BufReadCmd", EVENT_BUFREADCMD},
{"BufReadPost", EVENT_BUFREADPOST},
@@ -131,7 +131,7 @@
https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105
-
+
{"BufWrite", EVENT_BUFWRITEPRE},
{"BufWritePost", EVENT_BUFWRITEPOST},
{"BufWritePre", EVENT_BUFWRITEPRE},
@@ -148,7 +148,7 @@
https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124
-
+
aliases = {
BufCreate = 'BufAdd',
BufRead = 'BufReadPost',
@@ -161,7 +161,7 @@ FileEncoding = 'EncodingChanged',
ところで、上では取り上げなかったFileEncodingだが、これは:help FileEncodingにしっかりと書いてある。
-
+
*FileEncoding*
FileEncoding Obsolete. It still works and is equivalent
to |EncodingChanged|.
diff --git a/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html b/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html
index afe6ba9..8a3b304 100644
--- a/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html
+++ b/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html
@@ -115,7 +115,7 @@
なお、:g/^/m0は全ての行を入れ替えるが、:N,Mg/^/mN-1とすることで N行目から M行目を処理範囲とするよう拡張できる。手でこれを入力するわけにはいかないので、次のようなコマンドを用意する。
-
+
command! -bar -range=%
\ Reverse
\ <line1>,<line2>g/^/m<line1>-1
@@ -152,7 +152,7 @@
前述した:Reverseコマンドの定義を少し変えて、次のようにする:
-
+
function! s:reverse_lines(from, to) abort
execute printf("%d,%dg/^/m%d", a:from, a:to, a:from - 1)
endfunction
@@ -211,7 +211,7 @@
-
+
command! -bar -range=%
\ Reverse
\ keeppatterns <line1>,<line2>g/^/m<line1>-1
@@ -230,7 +230,7 @@
コピペ用再掲
-
+
" License: Public Domain
command! -bar -range=%
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 aee9c7c..d16739b 100644
--- a/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html
+++ b/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html
@@ -66,7 +66,7 @@
ソースコードはこちら。実行には PHP 8.1 以上が必要なので注意。
-
+
<?php
declare(strict_types=0O1);
@@ -165,7 +165,7 @@
なお、brainf*ck プログラムを普通の書き方で書くと、次のようになる。
-
+
+ + + + + + + + + +
[
> + + +
@@ -271,7 +271,7 @@
ソースコードのライセンスを示したこの部分だが、
-
+
https://creativecommons.org/publicdomain/zero/1.0/
@@ -286,7 +286,7 @@
ソースコード中に、ほとんど数値リテラルが書かれていないことにお気づきだろうか。 PHP では、型変換を利用することで任意の整数を作り出すことができる。
-
+
assert(0 === +!![]);
assert(1 === +![]);
assert(2 === ![]+![]);
@@ -333,7 +333,7 @@ assert(10 === +(![].+!![]));
ソースコードはこちら。実行には PHP 8.0 以上が必要なので注意。
-
+
<?php
/*********************************************************
@@ -384,7 +384,7 @@ assert(10 === +(![].+!![]));
まずはソースコードを読んでいく。
-
+
$token = [
// 略
];
@@ -394,7 +394,7 @@ assert(10 === +(![].+!![]));
数値からなる$tokenがあり、各要素をループしている。
-
+
$x = $x ^ N;
@@ -402,7 +402,7 @@ assert(10 === +(![].+!![]));
まずは排他的論理和 (xor) を取り、
-
+
$x = sprintf('%025b', $x);
@@ -410,7 +410,7 @@ assert(10 === +(![].+!![]));
二進数に変換して、
-
+
$x = str_replace(search: ['0', '1'], replace: [' ', '#'], subject: $x);
@@ -418,7 +418,7 @@ assert(10 === +(![].+!![]));
0 を空白に、1 を#にし、
-
+
$x = implode("\n", str_split($x, length: 5));
@@ -474,7 +474,7 @@ assert(10 === +(![].+!![]));
Nは高々
-
+
assert(0 <= N && N <= 0b11111_11111_11111_11111_11111);
@@ -482,7 +482,7 @@ assert(10 === +(![].+!![]));
なのでブルートフォースしてもよいが、ここではブルートフォースしない方法を紹介する。
-
+
<?php
$x = 0x14B499C;
@@ -505,7 +505,7 @@ assert(10 === +(![].+!![]));
この一連の変換に対する逆変換を考えると、次のようになる。
-
+
<?php
$x =
@@ -536,7 +536,7 @@ echo "N = $n\n";
ソースコードはこちら。
-
+
<?php
// License: https://creativecommons.org/publicdomain/zero/1.0/
@@ -572,7 +572,7 @@ echo "N = $n\n";
コメントにもあるとおり、次のようにして実行すれば答えがでてくる。
-
+
$ php toquine.php | php | php | php | ...
diff --git a/public/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal/index.html b/public/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal/index.html
index 5acfb32..bf174b8 100644
--- a/public/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal/index.html
+++ b/public/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal/index.html
@@ -43,7 +43,7 @@
こんなものを作った。
-
+
$ term-banner 'Hello, World!' 'こんにちは、' '世界!'
diff --git a/public/posts/2022-08-27/php-conference-okinawa-code-golf/index.html b/public/posts/2022-08-27/php-conference-okinawa-code-golf/index.html
index d8b8502..fbac1f0 100644
--- a/public/posts/2022-08-27/php-conference-okinawa-code-golf/index.html
+++ b/public/posts/2022-08-27/php-conference-okinawa-code-golf/index.html
@@ -111,7 +111,7 @@
書いたものがこちら:
-
+
[<?php $n=$argv[1];foreach([1e4,5e3,2e3,1e3,500,100,50,10,5,1]as$x)for(;$n>=$x;$n-=$x)$r[]=$x;echo implode(', ',$r??[]);?>]
@@ -123,7 +123,7 @@
こちらは改行とスペースを追加したバージョン:
-
+
[<?php
$n = $argv[1];
diff --git a/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html b/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html
index b121725..abdb48e 100644
--- a/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html
+++ b/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html
@@ -125,7 +125,7 @@
特に、C言語でこのような試みをおこなったことがあるかたならそう思うだろう。事実、Cでのこの制約はほとんど無意味に等しい。
-
+
#\
i\
n\
@@ -260,7 +260,7 @@
また、2文字だと文字列がまともに書けないのも辛い。''だけで 2文字使うので、「1文字の文字列リテラル」というものを書くことができない。PHP では文字列リテラル中に生の改行が書けるので
-
+
$a
='
a'
@@ -284,7 +284,7 @@ a'
まずは普通に書くとしよう。
-
+
<?php
for ($i = 1; $i < 100; $i++) {
@@ -303,7 +303,7 @@ a'
forは、3文字もある長いキーワードである。こんなものは使えない。array_系の関数を使って、適当に置き換えるとしよう。
-
+
<?php
$s = range(1, 100);
@@ -325,7 +325,7 @@ a'
range、array_walk、printfは長すぎるのでどうにかせねばならない。ここで、PHP の可変関数を使う。可変関数とは、関数名が文字列として入った変数を経由して、関数を呼び出す機能である。
-
+
<?php
$r = 'range';
@@ -365,7 +365,7 @@ a'
というルールがない場合、「未定義の定数が評価された場合、その定数の名前が値になる」という PHP 7.x までの仕様が利用できる。例えば、Fizzという文字列が欲しければ、次のようにする。
-
+
$f
=F
.i
@@ -378,7 +378,7 @@ a'
こうして簡単に文字列を作れる。なお、この仕様は 7.x 時点でも警告を受けるので、@演算子を使って抑制してやるとよい。
-
+
$f
=@
F.
@@ -405,7 +405,7 @@ F.
ずばり、文字列同士のビット演算を使う。PHP では、文字列同士でビット演算 (&、|、^) をした場合、文字列の各バイトごとに指定したビット演算がなされ、それを結合したものが演算結果となる。
-
+
$a = "12345";
$b = "world";
@@ -423,7 +423,7 @@ echo $result;
これを踏まえ、次のコードを見てみよう。
-
+
$x = "x\nOm\n";
$y = "\nk!\no";
$r = $x ^ $y;
@@ -434,7 +434,7 @@ echo "$r\n";
実行すると、rangeが表示される。さて、PHP では文字列リテラル中に生の改行を直接書いてもよいのだった (「主な障害」の節を参照のこと)。書きかえてみよう。
-
+
$x
='x
Om
@@ -453,7 +453,7 @@ echo "$r\n";
さらに#を使って適当に調整すると、次のようになる。
-
+
$x
=#
'x
@@ -490,7 +490,7 @@ echo "$r\n";
完成したものがこちら。
-
+
<?php
$x
@@ -660,7 +660,7 @@ echo "$r\n";
PHP では、バッククォートを使ってシェルを呼び出せる。これはshell_exec関数と等価である。さて、PHP ではバックスラッシュによる行継続が使えないと書いたが、シェルでは使える (当然だが、呼び出されるシェルに依存する。Bash なら大丈夫だろう。知らんけど)。
-
+
<?php
printf(`
@@ -701,7 +701,7 @@ echo "$r\n";
もうこれ以上は不可能だと思っていたのだが、この記事の執筆中に解決する方法を思いついたので載せておく。
-
+
<?php
$c = 'chr';
@@ -737,7 +737,7 @@ ${
先程と同じく、chrやprintfを生成する部分は長くなるので省いた。
-
+
${
'_
'}
@@ -747,7 +747,7 @@ ${
は変数で、中にはスペースとエスケープが入っている (chr(32) . chr(92))。シェルに渡されている文字列は次のようになる。
-
+
e\
c\
h\
@@ -770,7 +770,7 @@ o\
ちなみに、PHP 8.2 からは、この記法で Warning が出るようになるようだ。
-
+
${
'_
'}
diff --git a/public/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/index.html b/public/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/index.html
index da4cfea..a2bf44c 100644
--- a/public/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/index.html
+++ b/public/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/index.html
@@ -68,7 +68,7 @@
注意: これはボツ問なので、得られたトークンを PHPerKaigi で入力してもポイントにはならない。
-
+
<?php
$π = $argv[1] ?? null;
@@ -99,7 +99,7 @@ echo "Failed.\n";
ソースを見るとわかるとおり、$argv[1]を参照している。それを$πなる変数に代入しているので、円周率を渡してみる。
-
+
$ php Q.php 3.14
Failed.
@@ -108,7 +108,7 @@ echo "Failed.\n";
失敗してしまった。精度を上げてみる。
-
+
$ php Q.php 3.1415
Failed.
@@ -121,7 +121,7 @@ Failed.
最初にトークンが得られるのは、小数点以下 16 桁目まで入力したときで、こうなる。
-
+
$ php Q.php 3.1415926535897932
Token: #YO
@@ -137,7 +137,7 @@ Token: #YO
短いので頭から追っていく。
-
+
$π = $argv[1] ?? null;
if ($π === null) {
exit('No input.');
@@ -152,7 +152,7 @@ Token: #YO
入力のバリデーション部分。数値のみ受け付ける。
-
+
$s = implode(array_map(chr(...), str_split($π, 2)));
@@ -164,14 +164,14 @@ Token: #YO
例えば、$πが'656667'だったとすると、65、66、67に対応した'A'、'B'、'C'へと変換され、'ABC'になる。
-
+
$π = '656667';
$s = implode(array_map(chr(...), str_split($π, 2)));
echo $s;
// => ABC
-
+
preg_match('/(\x23.+?) /', $s, $m);
$t = $m[1] ?? '';
@@ -184,7 +184,7 @@ $t = $m[1] ?? '';
なお、#を直接書いていないのは、/#.+?) /と書くと、#.+?)という意図せぬトークンが登録されてしまうからである。
-
+
if (md5($t) === '056e831a4146bf123e8ea16613303d2e') {
echo "Token: {$t}\n";
} else {
diff --git a/public/posts/2022-10-28/setup-server-for-this-site/index.html b/public/posts/2022-10-28/setup-server-for-this-site/index.html
index 7f45478..6e002c3 100644
--- a/public/posts/2022-10-28/setup-server-for-this-site/index.html
+++ b/public/posts/2022-10-28/setup-server-for-this-site/index.html
@@ -73,7 +73,7 @@
ローカルマシンで鍵を生成する。
-
+
$ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/teika.key
$ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/github2teika.key
@@ -89,7 +89,7 @@
.ssh/configに設定しておく。
-
+
Host teika
HostName **********
User **********
@@ -114,7 +114,7 @@
管理者ユーザで作業すると危ないので、メインで使うユーザを作成する。sudoグループに追加してsudoできるようにし、suで切り替え。
-
+
$ sudo adduser **********
$ sudo adduser ********** sudo
$ su **********
@@ -124,14 +124,14 @@
ホスト名を変える
-
+
$ sudo hostname teika
公開鍵を置く
-
+
$ mkdir ~/.ssh
$ chmod 700 ~/.ssh
$ vi ~/.ssh/authorized_keys
@@ -148,7 +148,7 @@
SSH の設定を変更し、少しでも安全にしておく。
-
+
$ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
$ sudo vi /etc/ssh/sshd_config
@@ -177,7 +177,7 @@
そして設定を反映。
-
+
$ sudo systemctl restart sshd
$ sudo systemctl status sshd
@@ -189,7 +189,7 @@ $ sudo systemctl status sshd
今の SSH セッションは閉じずに、ターミナルを別途開いて疎通確認する。セッションを閉じてしまうと、SSH の設定に不備があった場合に締め出しをくらう。
-
+
$ ssh teika
@@ -200,7 +200,7 @@ $ sudo systemctl status sshd
デフォルトの 22 番を閉じ、設定したポートだけ空ける。
-
+
$ sudo ufw deny ssh
$ sudo ufw allow *******
$ sudo ufw enable
@@ -219,7 +219,7 @@ $ sudo systemctl status sshd
GitHub に置いてある private リポジトリをサーバから clone したいので、SSH 鍵を生成して置いておく。
-
+
$ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/github.key
$ cat ~/.ssh/github.key.pub
@@ -228,7 +228,7 @@ $ cat ~/.ssh/github.key.pub
GitHub の設定画面から、この公開鍵を追加する。
-
+
$ vi ~/.ssh/config
@@ -236,7 +236,7 @@ $ cat ~/.ssh/github.key.pub
設定はこう。
-
+
Host github.com
HostName github.com
User git
@@ -247,14 +247,14 @@ IdentityFile ~/.ssh/github.key
最後に接続できるか確認しておく。
-
+
ssh -T github.com
パッケージの更新
-
+
$ sudo apt update
$ sudo apt upgrade
$ sudo apt update
@@ -275,14 +275,14 @@ IdentityFile ~/.ssh/github.key
使うソフトウェアのインストール
-
+
$ sudo apt install docker docker-compose git make
メインユーザが Docker を使えるように
-
+
sudo adduser ********** docker
@@ -293,7 +293,7 @@ IdentityFile ~/.ssh/github.key
80 番と 443 番を空ける。
-
+
$ sudo ufw allow 80/tcp
$ sudo ufw allow 443/tcp
$ sudo ufw reload
@@ -303,7 +303,7 @@ IdentityFile ~/.ssh/github.key
リポジトリのクローン
-
+
$ cd
$ git clone git@github.com:nsfisis/nsfisis.dev.git
$ cd nsfisis.dev
@@ -313,7 +313,7 @@ IdentityFile ~/.ssh/github.key
certbot で証明書取得
-
+
$ docker-compose up -d acme-challenge
$ make setup
@@ -321,7 +321,7 @@ IdentityFile ~/.ssh/github.key
サーバを稼動させる
-
+
$ make serve
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
index f080c5e..7aa97a9 100644
--- 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
@@ -72,7 +72,7 @@
注意: これはボツ問なので、得られたトークンを PHPerKaigi で入力してもポイントにはならない。
-
+
<?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");?>
@@ -96,7 +96,7 @@
実行してみると、次のような出力が得られる。
-
+
#
<?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");?>
@@ -113,7 +113,7 @@
1 行目を除き、先ほどのコードとほぼ同じものが出てきた。もう一度実行してみる。
-
+
#
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");?>
@@ -130,7 +130,7 @@ W
今度は 2 行目が書き換えられた。すべての行が変化するまで繰り返すと次のようになる。
-
+
#
W
E
@@ -158,7 +158,7 @@ P
Vim で開くと次のようになる (1 行目を抜粋)。
-
+
<?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");?>
@@ -185,7 +185,7 @@ P
続いて、トークンへの変換ロジックを解析する。注目すべきはこの部分だ。以下、ゼロ幅スペースは Vim での表示に合わせて<200b>と記載する。
-
+
fn($s)=>chr(strlen($s)/3)
@@ -193,7 +193,7 @@ P
PHP のstrlen()は文字列のバイト数を返す。1 行目の$sは以下の内容となっており、
-
+
$s='<200b><?php printf((isset($s)?fn($s)=>trim($s,"<200b>"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'
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 6f9586a..3100b8e 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
@@ -82,7 +82,7 @@
注意: これはボツ問なので、得られたトークンを PHPerKaigi で入力してもポイントにはならない。
-
+
<?php
try {
f(g() / __LINE__);
@@ -239,7 +239,7 @@
このうち 1つ目のケースは、finally節の中でエラーを投げると PHP 処理系が勝手に$previousを設定してくれる。
-
+
<?php
try {
@@ -267,7 +267,7 @@
出力部をコメントや改行を追加して再掲する:
-
+
<?php
try {
f(g() / __LINE__);
@@ -287,7 +287,7 @@
フォーマット指定子%cは、整数を ASCII コードと見做して印字する。トークン#base64_decode('SGVsbG8sIFdvcmxkIQ==')のbであれば、ASCII コード98なので、75 行目で発生したエラー、
-
+
1, 20 => 0 / 0,
@@ -306,7 +306,7 @@
f()の定義を再掲する (エラーオブジェクトの行数を利用しているので、一部分だけ抜き出すと値が変わることに注意):
-
+
function f(int $i) {
if ($i < 0) f();
try {
@@ -333,13 +333,13 @@
前述のように、finally節でエラーを投げると PHP 処理系が$previousを設定する。ここでは、エラーを繋げるためにf()を再帰呼び出ししている。最初にf()を呼び出している箇所を確認すると、
-
+
<?php
try {
f(g() / __LINE__); // 3 行目
-
+
function g() {
return __LINE__; // 111 行目
}
--
cgit v1.2.3-70-g09d2