Bug #76046 [Opn]: PHP generates "FE_FREE" opcode on the wrong line.

From: Date: Thu, 18 Oct 2018 23:48:21 +0000
Subject: Bug #76046 [Opn]: PHP generates "FE_FREE" opcode on the wrong line.
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-217629@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=76046&edit=1

 ID:                 76046
 Updated by:         derick@php.net
 Reported by:        derick@php.net
 Summary:            PHP generates "FE_FREE" opcode on the wrong line.
 Status:             Open
 Type:               Bug
 Package:            Scripting Engine problem
 Operating System:   *
 PHP Version:        7.2.3
 Block user comment: N
 Private report:     N

 New Comment:

Hey,

would it be possible to add the ending line number of the foreach though? It'd be helpful for
people using code coverage.

cheers,
Derick


Previous Comments:
------------------------------------------------------------------------
[2018-03-03 12:06:19] nikic@php.net

We can't fix this right now, as we don't store the end line number of the foreach.

------------------------------------------------------------------------
[2018-03-03 11:58:22] derick@php.net

Description:
------------
This was originally filed as https://github.com/sebastianbergmann/php-code-coverage/issues/589
 and https://bugs.xdebug.org/view.php?id=1530
.

With the script:

  1 <?php
  2 foreach (['a'] as $item) {
  3     if (false) {
  4         echo "Test\n";
  5         echo "Test\n";
  6     }
  7 }
  8 ?>

I found that PHP generates the following opcodes (without opcache enabled):

filename:       /home/derick/dev/php/derickr-xdebug/tests/bug01530.inc
function name:  (null)
number of ops:  12
compiled vars:  !0 = $item
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   2     0  E >   EXT_STMT                                                 
         1      > FE_RESET_R                                       $1      <array>, ->10
         2    > > FE_FETCH_R                                               $1, !0, ->10
   3     3    >   EXT_STMT                                                 
         4      > JMPZ                                                     <false>, ->9
   4     5    >   EXT_STMT                                                 
         6        ECHO                                                     'Test%0A'
   5     7        EXT_STMT                                                 
         8        ECHO                                                     'Test%0A'
         9    > > JMP                                                      ->2
        10    >   FE_FREE                                                  $1
   9    11      > RETURN                                                   1

The foreach keyword is represented by opcode 1 and 2 (FE_RESET_R and FE_FETCH_R), and you see that
they can both jump to opcode 10 (->10). It would do that if the loop is empty (FE_RESET_R) or
exhausted (FE_FETCH_R). PHP has generated opcode 10 (FE_FREE) on line 5. Which is really not
correct, as it should put it on line 7. It does this wrong for both PHP 7.0, 7.1 and 7.2.


Test script:
---------------
 <?php
 foreach (['a'] as $item) {
     if (false) {
         echo "Test\n";
         echo "Test\n";
     }
 }
 ?>

Expected result:
----------------
   5     7        EXT_STMT                                                 
         8        ECHO                                                     'Test%0A'
         9    > > JMP                                                      ->2
   7    10    >   FE_FREE                                                  $1
   9    11      > RETURN                                                   1

Actual result:
--------------
   5     7        EXT_STMT                                                 
         8        ECHO                                                     'Test%0A'
         9    > > JMP                                                      ->2
        10    >   FE_FREE                                                  $1
   9    11      > RETURN                                                   1


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



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


Thread (4 messages)

« previous php.bugs (#217629) next »