2017-03-29 13 views
3

PHP言語に酷いバグがあるようです。変数変数を作成するときは、一見不正な変数を宣言して、変数変数としてアクセスし続ける限り処理することができます。 例:PHPの可変変数は不正な変数名を許可しますか?

${'0'} = 1;   //I am an illegal variable called $0 
${'0'}++;   //I can be accessed and manipulated. 
var_dump(${'0'}); //Output: int(2) 

この動作はかなり奇妙に見えます。ハイフンを含む変数名を作成する方法として、公式のSimpleXmlのドキュメントで簡単に言及されていますが、私の例ではそれにもかかわらず悪用される可能性があります。

私はこの動作がどのように可能で、コードが解析されたときに許容されるのか知りたいですか?

+1

私の仮定は、それが中括弧に包まれていますので、混同しパーサーのないチャンス、許容フォアありませんです。 – Scuzzy

+1

もし変数変数が許されない変数名を許さないならば、それは不適切な時(すなわち実行時)に壊れる傾向があります。これは、変数変数を使って行うことができるような遠隔操作ではありませんあなたはそれにあなたの心を入れます。 –

+0

phpは変数が$ 0だと思っています – Gert

答えて

3

arraysで使用されているものと同じデータ構造の内部でstores variableszend_array* symbol_table)です。これにより、配列キーと同じ制約を持つ変数名を持つことができます。

例: Zend API関数zend_set_local_varは、zend_hash_updateを使用してシンボルテーブルに値を設定します。これは、PHP配列タイプの操作にも使用されます。

ただし、PHPソースコードの変数名のすべての文字を許可することはできません。これは、字句解析ではラベルを他のトークンと区別する必要があるためです。変数変数は、これを回避する方法を提供します。

これはバグでも、悪用する方法でもありません。つまり、documentationは、変数を含むすべてのラベルが正規表現の形式[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*を持っていなければならないと述べています。したがって、変数名に任意の文字を使用することには依存しません。

${'0'} = 1;が実際に行うものは、値1を現在のスコープのシンボルテーブルのキー0に設定します。 get_defined_vars機能を使用して、その特定のテーブルを取得することができます。 source codeを見ると、関数は現在のシンボルテーブルをコピーして呼び出し元に返します。

PHP extract機能srcは実際にキーが(php_valid_var_nameを呼び出すことによって)有効なラベルフォーマットを持っていることを確認し、あなたがそれを使用してファンキーな名前の変数を生成することができません。

とにかく、可変変数構文(名前が${''}の変数も)を使用して任意の名前の変数を作成することは可能ですが、それは悪い習慣だと思います。図書館がそうすることを期待したり強制したりすればさらに悪化します。それが回避策だと言っても、実際は少し誇張かもしれません。おそらく、実装の詳細と文書化されていない機能として考慮する必要があります。私はそれについての完全なアイデアを持っていますが、少しのアイデアを持っていない

+0

あなたの説明は合理的ですが、最初の文章で書いたことを確認するのに問題があります。配列に使用されているのと同じデータ構造にPHPストア変数を検証するソースへの参照を追加できますか? – Nadav

+0

@Nadav:いくつかの参考文献を追加しました。同じデータ構造がシンボル(変数)と配列の両方に使用されているという事実は、単なる実装の詳細です。私もこれに反映するために私の答えを編集しました。 – Joe

0

@Nadav、

は文字通りので、「中括弧の内側に何があるかを評価」を意味し、中括弧({})は、あなたが絞ることができます忘れないでください変数の作成あなたは$ {「0」} =あなたがチェック$ GLOBALS(配列)を使用したい場合は1 は、アレイ状に変数このhttp://php.net/manual/en/language.variables.php#73373

PHP店からそれをrefferedスーパーグローバル変数があるが行ったようにこれスクリプト内に存在する変数のすべての参照を持っており、変数名をキーとして格納し、値を変数値として格納します。以下のように仮定します。

<?php 
    ${'0'} = 1; // here php stores it as 0th index in the array 
    ${'1'} = 2; // here php stores it as 1th index in the array 
    $b = "I am b"; // here php stores it as bth index in the array 
    echo "<pre>"; 
    print_r($GLOBALS); 

出力:

Array 
(
    [_GET] => Array 
     (
     ) 

    [_POST] => Array 
     (
     ) 

    [_COOKIE] => Array 
     (
     ) 

    [_FILES] => Array 
     (
     ) 

    [GLOBALS] => Array 
*RECURSION* 
    [0] => 1 
    [1] => 2 
    [b] => I am b 
) 
関連する問題