ID:               17959
 Updated by:       [EMAIL PROTECTED]
 Reported By:      [EMAIL PROTECTED]
-Status:           Analyzed
+Status:           Open
 Bug Type:         Scripting Engine problem
 Operating System: linux
 PHP Version:      4.2.1
 Assigned To:      hholzgra


Previous Comments:
------------------------------------------------------------------------

[2002-07-29 06:50:20] [EMAIL PROTECTED]

<?php
// Dear Php developer,
//
// After considering your explanation of what exactly 'global $ptr'
// is i changed my code to strictly use $GLOBALS['ptr'].  However,
// after doing so my program still didn't function properly!
//
// I had to work a bit harder to come up with a simplified example
// for you.  I believe i have done so below.
//
// Please pay close attention to the notes w/in comments explaining
// strange conditions that would make this sample code to work as
// expected.  Now I'm certain there EXISTS a serious problem with
// the Php engine when processing this code.
//
// Thanks,
// --patrick

// define array we plan to navigate.
$top =
array
  (
  'name' => 'top',
  'A' => array
          (
          'name' => 'A',
          'A_a' => array
                    (
                    'name' => 'A_a',
                    'fn_1' => 'Aa_fn_1',
                    'fn_2' => 'Aa_fn_2',
                    'fn_3' => 'Aa_fn_3',
                    'A_a_1' => array
                                (
                                'name' => 'A_a_1',
                                'fn_1' => 'Aa1_fn_1',
                                'fn_2' => 'Aa1_fn_2',
                                ),
                    'A_a_2' => array
                                (
                                'name' => 'A_a_2',
                                'fn_1' => 'Aa2_fn_1',
                                'fn_2' => 'Aa2_fn_2',
                                ),
                    ),
          ),
  );

// setup "parent references" for each of the nodes.
$top['parent']              = null;
$top['A']['parent']         = &$top;
$top['A']['A_a']['parent']  = &$top['A'];
$top['A']['A_a']['A_a_1']['parent']  = &$top['A']['A_a'];
$top['A']['A_a']['A_a_2']['parent']  = &$top['A']['A_a'];
//$top['A']['A_a']['A_a_1']['parent']  = &$top['A']['A_a'];
  //
  // Note!
  // Here if we uncomment the above line the sample code will
  // magically WORK!
  //
  // Why does the order of initialization matter!?  And will the
  // code now break elsewhere?

// setup our reference to $top.  $ptr is what should change
// on every call to change_ptr(name).
$ptr  = &$top;

// change_ptr( name ) does the following w/some verbose
// messages to display the state of variables in question.
//
//    if ( ptr[name] )
//      ptr = ptr[name];
//
function change_ptr( $name )
{
  printf( "  change_ptr($name) " );

  if ( $GLOBALS['ptr'][$name] ) {
    // Setting up string for later printing.
    $before_change =
    sprintf( "before: \$GLOBALS['ptr']['name'] = %s",
                       $GLOBALS['ptr']['name'] );

    $GLOBALS['ptr'] = &$GLOBALS['ptr'][$name];

    $after_change =
    sprintf( "after: \$GLOBALS['ptr']['name'] = %s",
                      $GLOBALS['ptr']['name'] );

    printf( "<font color=\"green\"><b>CHANGED</b></font>:\n" );
    printf( "    %s\n     %s", $before_change, $after_change );
  }
  else
    printf( "<font color=\"red\"><b>NO CHANGE!</b></font>" );
    
  printf( "<br>\n" );
}
?>
<pre>
<?
// All of the following calls should succeed and print
// 'CHANGED'.  However, you will notice that the last call
// will fail to change $ptr to point to the 'parent' of
// $top['A']['A_a']['A_a_2'].
//
change_ptr('A');
change_ptr('A_a');
change_ptr('A_a_1');
change_ptr('parent');
change_ptr('A_a_2');
change_ptr('parent');
?>
</pre>

------------------------------------------------------------------------

[2002-07-23 16:24:54] [EMAIL PROTECTED]

think of the "global $p;" construct as a shortcut for
"$p = &$GLOBALS['p'];" 

so by assigning a new reference you are breaking the one to the global
variable

so you have to explicitly assign to $GLOBALS["p"] here

(marked as documentation problem)

------------------------------------------------------------------------

[2002-07-16 08:40:10] [EMAIL PROTECTED]

<?php
// Here is a slightly modified version of the original
// post (case 3).  I hope the lenght of this test-case
// acceptable as i do not know of a shorter example.
//
// Thanks,
// --patrick

// define array we plan to navigate.
$top =
array
  (
  'name' =>  'top',
  'A' => array ( 'name' =>  'A', ),
  'B' => array
          (
          'name' =>  'B',
          'B_b' => array ( 'name' =>  'B_b', ),
          ),
  );

// setup "parent references" for each of the nodes.
$top['parent']              = null;
$top['A']['parent']         = &$top;
$top['B']['parent']         = &$top;
$top['B']['B_b']['parent']  = &$top['B'];

// setup our reference to $top.  $ptr is what should change
// on every call to change_ptr(name).
$ptr  = &$top;

// $i and $iref are meant to demonstrate the inconsistency
// of manipulating references w/in functions.
$i    = 0;
$iref = &$i;

// change_ptr( name ) does the following w/some verbose
// messages to display the state of variables in question.
//
//    if ( ptr[name] )
//      ptr = ptr[name];
//
function change_ptr( $name )
{
  // This case demonstrates how change_ptr() function fails
  // to actually change the value of a global variable $ptr.
  //
  // Essentially 'global $ptr' seems to only be local to the
  // function scope and modifying its value seems to have no
  // bearing on the global var $ptr that is of interest.
  //
  // Please note that the demonstrated behavior is not
  // inconsistent with how $iref is treated.
  global  $ptr;
  global  $iref;
  $iref++;

  printf( "  change_ptr($name) " );

  if ( $ptr[$name] ) {
    // Setting up string for later printing.
    $before_change =
    sprintf( "before: \$ptr['name'] = %s", $ptr['name'] )
    . "\n    " .
    sprintf( "        \$GLOBALS['ptr']['name'] = %s",
             $GLOBALS['ptr']['name'] );

    $ptr = &$ptr[$name];

    $after_change =
    sprintf( "after: \$ptr['name'] = %s", $ptr['name'] )
    . "\n     " .
    sprintf( "       \$GLOBALS['ptr']['name'] = %s",
             $GLOBALS['ptr']['name'] );

    printf( "<font color=\"green\">CHANGED</font>:\n" );
    printf( "    %s\n     %s", $before_change, $after_change );
  }
  else
    printf( "<font color=\"red\">NO CHANGE!</font>" );
    
  printf( "\n     \$iref: $iref" );
  printf( "\n     \$GLOBALS['iref']: $iref<br>\n" );
}
?>
<pre>
<?
// The first call to change_ptr('B') is expected to change
// globally defined $ptr to become $ptr['B'], hence, the
// 2nd call to the change_ptr('B') should fail since 
// $top['B']['B'] does not exist.
change_ptr('B');
change_ptr('B'); // What is going on??
                 // Why didn't previous call stick?
?>
</pre>

------------------------------------------------------------------------

[2002-07-13 18:29:59] [EMAIL PROTECTED]

Please provide a SHORT reproducing script.

Derick

------------------------------------------------------------------------

[2002-06-25 00:41:53] [EMAIL PROTECTED]

<?php
  //
  // There seems to be some issues with how array references
  // are handled by PHP, unless, my understanding of how
  // array()s and references to them are supposed to work is
  // seriously flawed.
  //
  // Unfortunately i don't have enough time on my hands to
  // dig through PHP sources.
  //
  // The source below seems to be a few very simple test-cases
  // pointing out the bug that's caused me enough grief.
  // Hopefully, someone can use this information in tracking
  // down the bug and eventually fixing it.
  //
  // The following issues can be duplicated on both
  // PHP Versions 4.1.2 and 4.2.1
  //
  // I'm not much concerned about 'Case 1' as I am about
  // cases 3 and 4.  They seem more serious problems.
  //
?>
<?  // -- Case 1
    // This case demonstrates that $top['B']['B_b']['parent'] loses
    // the reference to parent array!
    //
  $top =
  array
    (
    'name'    =>  'top',
    'parent'  =>  null,
    'A' =>
      array
        (
        'name'    =>  'A',
        'parent'  =>  &$top,
        ),
    'B' =>
      array
        (
        'name'    =>  'B',
        'parent'  =>  &$top,
        'B_b' =>
          array
            (
            'name'    =>  'B_b',
            'parent'  =>  &$top['B'],
            ),
        ),
    );
?>
<pre>
case 1:
  top:
<?
  foreach ( $top as $k => $v ) {
    printf( "    $k =&gt; $v\n" );
  }
?>
</pre>
<pre>
  top['A']:
<?
  foreach ( $top['A'] as $k => $v ) {
    printf( "    $k =&gt; $v\n" );
  }
?>
</pre>
<pre>
  top['B']:
<?
  foreach ( $top['B'] as $k => $v ) {
    printf( "    $k =&gt; $v\n" );
  }
?>
</pre>
<pre>
  top['B']['B_b']:
<?
  foreach ( $top['B']['B_b'] as $k => $v ) {
    printf( "    $k =&gt; $v\n" );
  }
  //
  // What happened to $top['B']['B_b']['parent'] reference?
  //
?>
</pre>
<hr align="left" size="5" width="80%">

<?  // -- Case 2
    // This case shows a work around to above bug.
    //
  $top =
  array
    (
    'name'    =>  'top',
    //'parent'  =>  null,
    'A' =>
      array
        (
        'name'    =>  'A',
        //'parent'  =>  &$top,
        ),
    'B' =>
      array
        (
        'name'    =>  'B',
        //'parent'  =>  &$top,
        'B_b' =>
          array
            (
            'name'    =>  'B_b',
            //'parent'  =>  &$top['B'],
            ),
        ),
    );
$top['parent']              = null;
$top['A']['parent']         = &$top;
$top['B']['parent']         = &$top;
$top['B']['B_b']['parent']  = &$top['B'];
?>
<pre>
case 2:
  top:
<?
  foreach ( $top as $k => $v ) {
    printf( "    $k =&gt; $v\n" );
  }
?>
</pre>
<pre>
  top['A']:
<?
  foreach ( $top['A'] as $k => $v ) {
    printf( "    $k =&gt; $v\n" );
  }
?>
</pre>
<pre>
  top['B']:
<?
  foreach ( $top['B'] as $k => $v ) {
    printf( "    $k =&gt; $v\n" );
  }
?>
</pre>
<pre>
  top['B']['B_b']:
<?
  foreach ( $top['B']['B_b'] as $k => $v ) {
    printf( "    $k =&gt; $v\n" );
  }
?>
</pre>
<hr align="left" size="5" width="80%">
<pre>
case 3:
<?  // -- Case 3
    // This case demonstrates how change_ptr() function fails to
actually
    // change the value of a global variable $ptr.
    //
    // Essentially 'global $ptr' seems to only be local to the
function
    // scope and modifying its value seems to have no bearing on the
    // global variable $ptr that we are interested in!!
    //
    // Please note that the demonstrated behavior is inconsistant with
    // how $iref is treated.
    //
  $ptr  = &$top;
  $i    = 0;
  $iref = &$i;

  function change_ptr( $name )
  {
    global  $ptr;
    global  $iref;
    $iref++;

    printf( "  change_ptr($name) " );

    if ( $ptr[$name] ) {
      $before_change =
      sprintf( "before: \$ptr['name'] = %s", $ptr['name'] ) . "\n    "
.
      sprintf( "        \$GLOBALS['ptr']['name'] = %s",
$GLOBALS['ptr']['name'] );

      $ptr = &$ptr[$name];

      $after_change =
      sprintf( "after: \$ptr['name'] = %s", $ptr['name'] ) . "\n     "
.
      sprintf( "       \$GLOBALS['ptr']['name'] = %s",
$GLOBALS['ptr']['name'] );

      printf( "<font color=\"green\">CHANGED</font>:\n" );
      printf( "    %s\n     %s", $before_change, $after_change );
    }
    else
      printf( "<font color=\"red\">NO CHANGE!</font>" );
      
    printf( "\n     \$iref: $iref<br>\n" );
  }

  change_ptr('B');
  change_ptr('B'); // what is going on??  Why didn't previous call
stick?
?>
</pre>
<hr align="left" size="5" width="80%">
<pre>
case 4:
<?  // -- Case 4
    // This case shows the expected behavior of 'Case 3'.
    //
  function change_ptr2( $name )
  {
    global  $iref;
    $iref++;

    printf( "  change_ptr2($name) " );

    if ( $GLOBALS['ptr'][$name] ) {
      $before_change =
      sprintf( "before: \$GLOBALS['ptr']['name'] = %s",
$GLOBALS['ptr']['name'] );

      $GLOBALS['ptr'] = &$GLOBALS['ptr'][$name];

      $after_change =
      sprintf( "after: \$GLOBALS['ptr']['name'] = %s",
$GLOBALS['ptr']['name'] );

      printf( "<font color=\"green\">CHANGED</font>:\n" );
      printf( "    %s\n     %s", $before_change, $after_change );
    }
    else
      printf( "<font color=\"red\">NO CHANGE!</font>" );
      
    printf( "\n     \$iref: $iref<br>\n" );
  }

  change_ptr2('B');
  change_ptr2('B'); // good! no change
  change_ptr2('B_b');
  change_ptr2('parent'); // Back to $top['B']
  change_ptr2('parent'); // Back to $top

  change_ptr2('A'); // This call will cause a problem soon!
  change_ptr2('parent');
  change_ptr2('B');
  change_ptr2('B_b');

  // And just as we were doing so well ...
  change_ptr2('parent');  // Grrr!  What happened!?!?

  // apparently the call change_ptr2('A') screws something up.
?>
</pre>
<?
// ex: ai et sw=2 ts=2
?>

------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=17959&edit=1

Reply via email to