[xdebug-dev] xdebug xdebug/xdebug_code_coverage.c xdebug/tests/bug00470.inc xdebug/tests/bug00470.phpt xdebug/tests/bug00472.inc xdebug/tests/bug00472.phpt - Fixed bug #470: catch blocks marked as dead code unless executed.

From: Derick Rethans <derick[@]derickrethans.nl>
Date: Thu, 15 Oct 2009 18:25:02 +0200

Date: Thu Oct 15 18:25:02 CEST 2009
User: Derick Rethans
Directory: xdebug

Log Message:
[4.00]
- Fixed bug #470: catch blocks marked as dead code unless executed.
- Fixed bug #472: Dead Code Analysis for code coverage messed up after goto.

Modified files:
           xdebug/xdebug_code_coverage.c (version: 1.54)
Added files:
           xdebug/tests/bug00470.inc (new version: 1.1)
           xdebug/tests/bug00470.phpt (new version: 1.1)
           xdebug/tests/bug00472.inc (new version: 1.1)
           xdebug/tests/bug00472.phpt (new version: 1.1)

[FILE: /xdebug/xdebug_code_coverage.c]

===================================================================
RCS file: cvstemp,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -r1.53 -r1.54
--- xdebug/xdebug_code_coverage.c:1.53 Sat Jul 04 12:31:44 2009 GMT
+++ xdebug/xdebug_code_coverage.c Thu Oct 15 14:25:02 2009 GMT
@@ -155,6 +155,11 @@
                 *jmp1 = position + 1;
                 *jmp2 = opcode.op2.u.opline_num;
                 return 1;
+#if (PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3)
+ } else if (opcode.opcode == ZEND_GOTO) {
+ *jmp1 = ((long) opcode.op1.u.jmp_addr - (long) base_address) / sizeof(zend_op);
+ return 1;
+#endif
         }
         return 0;
 }
@@ -194,18 +199,7 @@
                 /* See if we have a throw instruction */
                 if (opa->opcodes[position].opcode == ZEND_THROW) {
                         /* fprintf(stderr, "Throw found at %d\n", position); */
- /* Now we need to go forward to the first
- * zend_fetch_class/zend_catch combo */
- while (position < opa->last) {
- if (opa->opcodes[position].opcode == ZEND_CATCH) {
- /* fprintf(stderr, "Found catch at %d\n", position); */
- position--;
- break;
- }
- position++;
- /* fprintf(stderr, "Skipping %d\n", position); */
- }
- position--;
+ break;
                 }
 
                 /* See if we have an exit instruction */
@@ -225,6 +219,20 @@
         }
 }
 
+static void xdebug_analyse_oparray(zend_op_array *opa, xdebug_set *set TSRMLS_DC)
+{
+ unsigned int position = 0;
+
+ while (position < opa->last) {
+ if (position == 0) {
+ xdebug_analyse_branch(opa, position, set TSRMLS_CC);
+ } else if (opa->opcodes[position].opcode == ZEND_CATCH) {
+ xdebug_analyse_branch(opa, position, set TSRMLS_CC);
+ }
+ position++;
+ }
+}
+
 static void prefill_from_oparray(char *fn, zend_op_array *opa TSRMLS_DC)
 {
         unsigned int i;
@@ -246,7 +254,7 @@
         /* Run dead code analysis if requested */
         if (XG(code_coverage_dead_code_analysis) && opa->done_pass_two) {
                 set = xdebug_set_create(opa->last);
- xdebug_analyse_branch(opa, 0, set);
+ xdebug_analyse_oparray(opa, set);
         }
 
         /* The normal loop then finally */

[FILE: /xdebug/tests/bug00470.inc]

<?php
class Ticket842
{
    public function __construct()
    {
        try {
            //
        } catch (Exception $e) {
            error_log($e->getMessage());
        }
    }
}
?>

[FILE: /xdebug/tests/bug00470.phpt]

--TEST--
Test for bug #470: catch blocks marked as dead code unless executed.
--SKIPIF--
<?php if (!extension_loaded("xdebug")) print "skip"; ?>
<?php if(version_compare(zend_version(), "2.0.0-dev", '<')) echo "skip Zend Engine 2 needed\n"; ?>
--INI--
xdebug.default_enable=1
xdebug.auto_trace=0
xdebug.trace_options=0
xdebug.trace_output_dir=/tmp
xdebug.collect_params=1
xdebug.collect_return=0
xdebug.collect_assignments=0
xdebug.auto_profile=0
xdebug.profiler_enable=0
xdebug.dump_globals=0
xdebug.show_mem_delta=0
xdebug.trace_format=0
xdebug.extended_info=1
--FILE--
<?php
    xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);

    include 'bug00470.inc';
    $cc = xdebug_get_code_coverage();
    array_shift($cc);
    var_dump($cc);

    new Ticket842;
    $cc = xdebug_get_code_coverage();
    array_shift($cc);
    var_dump($cc);

    xdebug_stop_code_coverage(false);
?>
--EXPECTF--
array(1) {
  ["%sbug00470.inc"]=>
  array(5) {
    [3]=>
    int(1)
    [8]=>
    int(-1)
    [9]=>
    int(-1)
    [11]=>
    int(-1)
    [14]=>
    int(1)
  }
}
array(1) {
  ["%sbug00470.inc"]=>
  array(5) {
    [3]=>
    int(1)
    [8]=>
    int(1)
    [9]=>
    int(-1)
    [11]=>
    int(1)
    [14]=>
    int(1)
  }
}

[FILE: /xdebug/tests/bug00472.inc]

<?php
/*
 * @author Elizabeth Smith <auroraeosrose[@]php.net>
 * @copyright Elizabeth Smith (c) 2009
 */
namespace Baalat;
abstract class Object {
    public function emit($name) {
        if (is_null($this->state)) {
            $this->state = new \SplObjectStorage();
        }

        $signal = self::getSignal($name);
        if (is_null($signal)) {
            throw new \InvalidArgumentException('Signal ' . $name . ' is not a registered signal of ' . get_class($this));
        }

        if (isset($this->state[$signal]) && $this->state[$signal] === self::EMISSION_RUN) {
            $this->state[$signal] = self::EMISSION_RESTART;
            return;
        }

        if (isset(self::$blockedSignals[$signal->class])&& isset(self::$blockedSignals[$signal->class][$name])
            && self::$blockedSignals[$signal->class][$name] > 0) {
            $this->state[$signal] = self::EMISSION_STOP;
            return;
        }

        if (isset($this->blocked[$name]) && $this->blocked[$name] > 0) {
            $this->state[$signal] = self::EMISSION_STOP;
            return;
        }

        $args = func_get_args();
        array_shift($args);

        emit_restart:
            $this->state[$signal] = self::EMISSION_RUN;

            if ($signal->handler && $signal->run === Signal::RUN_FIRST) {
                $run = call_user_func_array(array($this, $signal->handler), $args);
                if ($this->state[$signal] === self::EMISSION_STOP) {
                    goto emit_cleanup;
                }
                if ($this->state[$signal] === self::EMISSION_RESTART) {
                    goto emit_restart;
                }
            }

            if (isset(self::$hooks[$signal->class]) && isset(self::$hooks[$signal->class][$name])) {
                foreach(self::$hooks[$signal->class][$name] as $handler) {
                    $run = call_user_func_array($handler['handler'], $args + $handler['args']);

                    if ((!$signal->accumulator && $run === true) ||
                        ($signal->accumulator && call_user_func(array($this, $signal->accumulator), $run) === true)) {
                        goto emit_cleanup;
                    } else if ($this->state[$signal] === self::EMISSION_STOP) {
                        goto emit_cleanup;
                    } else if ($this->state[$signal] === self::EMISSION_RESTART) {
                        goto emit_restart;
                    }
                }
            }

            if (isset($this->handlers[$name])) {
                foreach($this->handlers[$name] as $handler) {
                    if (!$handler['runlast'] && $handler['blocked'] < 1) {
                        $run = call_user_func_array($handler['handler'], $args + $handler['args']);

                        if ((!$signal->accumulator && $run === true) ||
                            ($signal->accumulator && call_user_func(array($this, $signal->accumulator), $run) === true)) {
                            goto emit_cleanup;
                        } else if ($this->state[$signal] === self::EMISSION_STOP) {
                            goto emit_cleanup;
                        } else if ($this->state[$signal] === self::EMISSION_RESTART) {
                            goto emit_restart;
                        }
                    }
                }
            }

            if ($signal->handler && $signal->run === Signal::RUN_LAST) {
                $run = call_user_func_array(array($this, $signal->handler), $args);
                if ($this->state[$signal] === self::EMISSION_STOP) {
                    goto emit_cleanup;
                }
                if ($this->state[$signal] === self::EMISSION_RESTART) {
                    goto emit_restart;
                }
 
            }

            if (isset($this->handlers[$name])) {
                foreach($this->handlers[$name] as $handler) {
                    if ($handler['runlast'] && $handler['blocked'] < 1) {
                        $run = call_user_func_array($handler['handler'], $args + $handler['args']);

                        if ((!$signal->accumulator && $run === true) ||
                            ($signal->accumulator && call_user_func(array($this, $signal->accumulator), $run) === true)) {
                            goto emit_cleanup;
                        } else if ($this->state[$signal] === self::EMISSION_STOP) {
                            goto emit_cleanup;
                        } else if ($this->state[$signal] === self::EMISSION_RESTART) {
                            goto emit_restart;
                        }
                    }
                }
            }

        emit_cleanup:

            if ($signal->handler && $signal->run === Signal::RUN_CLEANUP) {
                $run = call_user_func_array(array($this, $signal->handler), $args);
            }
            if ($this->state[$signal] === self::EMISSION_RESTART) {
                goto emit_restart;
            }
            $this->state[$signal] = self::EMISSION_STOP;
            return;
    }
}

[FILE: /xdebug/tests/bug00472.phpt]

--TEST--
Test for bug #472: Dead Code Analysis for code coverage messed up after goto.
--SKIPIF--
<?php if (!extension_loaded("xdebug")) print "skip"; ?>
<?php if(version_compare(zend_version(), "2.0.0-dev", '<')) echo "skip Zend Engine 2 needed\n"; ?>
--INI--
xdebug.default_enable=1
xdebug.auto_trace=0
xdebug.trace_options=0
xdebug.trace_output_dir=/tmp
xdebug.collect_params=1
xdebug.collect_return=0
xdebug.collect_assignments=0
xdebug.auto_profile=0
xdebug.profiler_enable=0
xdebug.dump_globals=0
xdebug.show_mem_delta=0
xdebug.trace_format=0
xdebug.extended_info=1
--FILE--
<?php
    xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);

        include 'bug00472.inc';
    $cc = xdebug_get_code_coverage();
        array_shift($cc);
        var_dump($cc);

    xdebug_stop_code_coverage(false);
?>
--EXPECTF--
array(1) {
  ["%sbug00472.inc"]=>
  array(95) {
    [7]=>
    int(1)
    [9]=>
    int(-1)
    [10]=>
    int(-1)
    [11]=>
    int(-1)
    [13]=>
    int(-1)
    [14]=>
    int(-1)
    [15]=>
    int(-1)
    [16]=>
    int(-2)
    [18]=>
    int(-1)
    [19]=>
    int(-1)
    [20]=>
    int(-1)
    [21]=>
    int(-2)
    [23]=>
    int(-1)
    [24]=>
    int(-1)
    [25]=>
    int(-1)
    [26]=>
    int(-1)
    [27]=>
    int(-2)
    [29]=>
    int(-1)
    [30]=>
    int(-1)
    [31]=>
    int(-1)
    [32]=>
    int(-2)
    [34]=>
    int(-1)
    [35]=>
    int(-1)
    [38]=>
    int(-1)
    [40]=>
    int(-1)
    [41]=>
    int(-1)
    [42]=>
    int(-1)
    [43]=>
    int(-1)
    [44]=>
    int(-2)
    [45]=>
    int(-1)
    [46]=>
    int(-1)
    [47]=>
    int(-2)
    [48]=>
    int(-1)
    [50]=>
    int(-1)
    [51]=>
    int(-1)
    [52]=>
    int(-1)
    [54]=>
    int(-1)
    [55]=>
    int(-1)
    [56]=>
    int(-1)
    [57]=>
    int(-1)
    [58]=>
    int(-1)
    [59]=>
    int(-1)
    [60]=>
    int(-1)
    [61]=>
    int(-2)
    [62]=>
    int(-1)
    [63]=>
    int(-1)
    [65]=>
    int(-1)
    [66]=>
    int(-1)
    [67]=>
    int(-1)
    [68]=>
    int(-1)
    [70]=>
    int(-1)
    [71]=>
    int(-1)
    [72]=>
    int(-1)
    [73]=>
    int(-1)
    [74]=>
    int(-1)
    [75]=>
    int(-1)
    [76]=>
    int(-1)
    [77]=>
    int(-2)
    [78]=>
    int(-1)
    [79]=>
    int(-1)
    [80]=>
    int(-1)
    [82]=>
    int(-1)
    [83]=>
    int(-1)
    [84]=>
    int(-1)
    [85]=>
    int(-1)
    [86]=>
    int(-2)
    [87]=>
    int(-1)
    [88]=>
    int(-1)
    [89]=>
    int(-2)
    [91]=>
    int(-1)
    [93]=>
    int(-1)
    [94]=>
    int(-1)
    [95]=>
    int(-1)
    [96]=>
    int(-1)
    [98]=>
    int(-1)
    [99]=>
    int(-1)
    [100]=>
    int(-1)
    [101]=>
    int(-1)
    [102]=>
    int(-1)
    [103]=>
    int(-1)
    [104]=>
    int(-1)
    [105]=>
    int(-2)
    [106]=>
    int(-1)
    [107]=>
    int(-1)
    [108]=>
    int(-1)
    [112]=>
    int(-1)
    [113]=>
    int(-1)
    [114]=>
    int(-1)
    [115]=>
    int(-1)
    [116]=>
    int(-1)
    [117]=>
    int(-2)
    [118]=>
    int(-1)
    [119]=>
    int(-1)
    [120]=>
    int(-2)
    [122]=>
    int(1)
  }
}
Received on Thu Oct 15 2009 - 18:25:24 BST

This archive was generated by hypermail 2.2.0 : Sun Jun 24 2018 - 04:00:03 BST