php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #76046 PHP generates "FE_FREE" opcode on the wrong line.
Submitted: 2018-03-03 11:58 UTC Modified: 2018-10-18 23:48 UTC
Votes:4
Avg. Score:3.2 ± 1.5
Reproduced:3 of 3 (100.0%)
Same Version:3 (100.0%)
Same OS:2 (66.7%)
From: derick@php.net Assigned:
Status: Closed Package: Scripting Engine problem
PHP Version: 7.2.3 OS: *
Private report: No CVE-ID: None
 [2018-03-03 11:58 UTC] 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

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-03-03 12:06 UTC] nikic@php.net
We can't fix this right now, as we don't store the end line number of the foreach.
 [2018-10-18 23:48 UTC] derick@php.net
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
 [2018-11-27 15:40 UTC] nikic@php.net
Automatic comment on behalf of nikita.ppv@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=d6595f276fff44aa5d1d2dde7238d540a267d0dd
Log: Fixed bug #76046
 [2018-11-27 15:40 UTC] nikic@php.net
-Status: Open +Status: Closed
 
PHP Copyright © 2001-2018 The PHP Group
All rights reserved.
Last updated: Mon Dec 10 01:01:24 2018 UTC