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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: derick@php.net
New email:
PHP Version: OS:

 

 [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

Pull Requests

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-2024 The PHP Group
All rights reserved.
Last updated: Sun Nov 24 06:01:32 2024 UTC