PHPの脆弱性探しで、PHPのソースコードを徘徊してたら、以下のようなテストコードにぶつかりました。
--TEST--
ctype on strings
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--FILE--
<?php
setlocale(LC_ALL,"C");
print "LOCALE is '" . setlocale(LC_ALL,0) . "'\n";
function ctype_test_002($function) {
$n1 = $n2 = $n3 = 0;
// test portable POSIX characters 0..127
for ($a=0;$a<128;$a++) {
$c = chr($a);
if($function($a)) $n1++;
if($function("$c$c$c")) $n2++;
if($function("1-$c$c$c-x")) $n3++;
}
print "$function $n1 $n2 $n3\n";
}
ctype_test_002("ctype_lower");
ctype_test_002("ctype_upper");
ctype_test_002("ctype_alpha");
ctype_test_002("ctype_digit");
ctype_test_002("ctype_alnum");
ctype_test_002("ctype_cntrl");
ctype_test_002("ctype_graph");
ctype_test_002("ctype_print");
ctype_test_002("ctype_punct");
ctype_test_002("ctype_space");
ctype_test_002("ctype_xdigit");
?>
--EXPECTF--
LOCALE is '%s'
ctype_lower 26 26 0
ctype_upper 26 26 0
ctype_alpha 52 52 0
ctype_digit 10 10 0
ctype_alnum 62 62 0
ctype_cntrl 33 33 0
ctype_graph 94 94 94
ctype_print 95 95 95
ctype_punct 32 32 0
ctype_space 6 6 0
ctype_xdigit 22 22 0
ctypeとは、文字タイプを判別する関数群のようで、ここでは、
ctype_lower
ctype_upper
ctype_alpha
ctype_digit
ctype_alnum
ctype_cntrl
ctype_graph
ctype_print
ctype_punct
ctype_space
ctype_xdigit
などの関数が実行されています。
setlocale(LC_ALL,"C");
で、ロケールを"C"にする。"C"とは、アプリケーションのデフォルトのロケールのことで、例えば、ユーザーがロケールを変更していた場合でも、アプリケーションのデフォルトのロケールに戻す。
setlocale(LC_ALL,0)
この関数は、現在設定されているロケールを文字列で返す関数です。"C"が設定されていることを確認していますね。
function ctype_test_002($function)
この関数の、$functionに、関数名の文字列を渡すことで、関数を渡すことになる。
chr($a)
chr関数は、0から255までの値を引数として設定できます。以下のように、256以上の場合は、256で割った余りの数字のasciiコードを返します。0以下の場合は、0以上になるまで、256を足されます。
while ($ascii < 0) {
$ascii += 256;
}
$ascii %= 256;
ここでは、0から127までしか使ってないですね。これには、空白、記号、数字、大文字のアルファベット、小文字のアルファベットが入ります。
$function($a)
この関数によって、$aが、そのまま、$functionに定義された関数に引数として入力されます。
$functionが"ctype_lower"として定義されていると、$aが小文字に対応する数字の時だけ、trueを返します。
ここでは、chrでascii文字に変換する前の、ただの数字を入力しています。この時も、該当する文字が小文字の時は、trueを返します。具体的には、97から122です。
$function("$c$c$c")
この関数によって、ascii文字が、3つ連結された文字列が、$functionに引数として導入されます。$function($a)と同じく、$functionが"ctype_lower"として定義されていると、$cが小文字の時だけ、trueを返します。
$function("1-$c$c$c-x")
この場合、例えば、$functionが、"ctype_lower"に定義されていて、$cが小文字だったとしても、trueは返されません。理由は、1と-が混じっていて、これらはアルファベットの小文字ではないからです。
しかし、$functionが"ctype_print"に定義されていると、$cが印字可能な文字が入力されていた場合、trueが返されます。なぜかというと、1と-が共に印字可能だからです。
ところで、最近は、技術ブログを書きたいなら、OSSのソースコードを読んだ方がいいのではと考え始めました。ということで、これからもOSSのソースコードを読んでいこうかと思います。
これからもよろしくお願いします。