これはTokenizerの仕事のようですね!
を使用して、解析されたすべてのトークンを PHP ソース ファイルから取得できますtoken_get_all
。次に、結果の配列を調べて、各トークンを 1 つずつ評価できます。トークン名は、 を使用して検索できる番号として返されますtoken_name
。
PHP インタラクティブ プロンプトでの小さなデモ:
php > $str = '<?php echo $face[fire]; echo $face[\'fire\']; ?>';
php > $t = token_get_all($str);
php > foreach($t as $i => $j) { if(is_array($j)) $t[$i][0] = token_name($j[0]); }
そして、これは別のコード ブロックでの出力です。これは少し背が高く、スクロールしながらソース文字列を参照するのに適しているためです。
php > print_r($t);
Array
(
[0] => Array
(
[0] => T_OPEN_TAG
[1] => <?php
[2] => 1
)
[1] => Array
(
[0] => T_ECHO
[1] => echo
[2] => 1
)
[2] => Array
(
[0] => T_WHITESPACE
[1] =>
[2] => 1
)
[3] => Array
(
[0] => T_VARIABLE
[1] => $face
[2] => 1
)
[4] => [
[5] => Array
(
[0] => T_STRING
[1] => fire
[2] => 1
)
[6] => ]
[7] => ;
[8] => Array
(
[0] => T_WHITESPACE
[1] =>
[2] => 1
)
[9] => Array
(
[0] => T_ECHO
[1] => echo
[2] => 1
)
[10] => Array
(
[0] => T_WHITESPACE
[1] =>
[2] => 1
)
[11] => Array
(
[0] => T_VARIABLE
[1] => $face
[2] => 1
)
[12] => [
[13] => Array
(
[0] => T_CONSTANT_ENCAPSED_STRING
[1] => 'fire'
[2] => 1
)
[14] => ]
[15] => ;
[16] => Array
(
[0] => T_WHITESPACE
[1] =>
[2] => 1
)
[17] => Array
(
[0] => T_CLOSE_TAG
[1] => ?>
[2] => 1
)
)
ご覧のとおり、悪意のある配列インデックスは、a のT_VARIABLE
後に開き括弧が続き、次に引用符で囲まれていないT_STRING
aです。単一引用符で囲まれたインデックスは、 、引用符などとして表示されます。T_CONSTANT_ENCAPSED_STRING
この知識があれば、トークンのリストを調べて、実際にソースを書き直して、引用符で囲まれていない配列インデックスをすべて削除できます。それらのほとんどは明らかなはずです。ファイルを書き戻すときに、文字列を一重引用符で囲むだけです。
望ましくない副作用が確実に発生するため、数値インデックスを引用したくないことに注意してください。
また、式はインデックス内で有効であることにも注意してください。
$pathological[ some_function('Oh gods', 'why me!?') . '4500' ] = 'Teh bad.';
自動化されたツールを使用してこれらを処理するのは、ごくわずかで、わずかに困難です。つまり、それらを処理しようとすると、殺人的な怒りに陥る可能性があります. 定数/文字列の問題のみを修正することをお勧めします。正しく行われれば、通知カウントをより管理しやすいレベルまで下げることができるはずです。
(また、Tokenizer はカーリー文字列構文を実際のトークンとして処理することにも注意してください。T_CURLY_OPEN
これにより、これらの厄介なインライン配列インデックスを処理しやすくなります。見逃した場合に備えて、すべてのトークンのリストをもう一度示します。)