Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.0.0]Seg fault on php5 when forwarding from beforeException #12154

Closed
Jurigag opened this issue Aug 20, 2016 · 7 comments
Closed

[3.0.0]Seg fault on php5 when forwarding from beforeException #12154

Jurigag opened this issue Aug 20, 2016 · 7 comments
Labels
bug A bug report status: medium Medium
Milestone

Comments

@Jurigag
Copy link
Contributor

Jurigag commented Aug 20, 2016

Expected and Actual Behavior

Should return test, but it doesn't, there is just seg fault when accessing just index page(/)

On php7 it works though.

Backtrace - http://pastebin.com/jD5GQJaJ

Github repo - https://github.com/Jurigag/phalcon-segfault-before-forward

Details

  • Phalcon version:
Web framework delivered as a C-extension for PHP
phalcon => enabled
Author => Phalcon Team and contributors
Version => 3.0.1
Build Date => Aug 20 2016 15:06:39
Powered by Zephir => Version 0.9.4a-dev-121e9b4bf1

Directive => Local Value => Master Value
phalcon.db.escape_identifiers => On => On
phalcon.db.force_casting => Off => Off
phalcon.orm.events => On => On
phalcon.orm.virtual_foreign_keys => On => On
phalcon.orm.column_renaming => On => On
phalcon.orm.not_null_validations => On => On
phalcon.orm.exception_on_failed_save => Off => Off
phalcon.orm.enable_literals => On => On
phalcon.orm.late_state_binding => Off => Off
phalcon.orm.enable_implicit_joins => On => On
phalcon.orm.cast_on_hydrate => Off => Off
phalcon.orm.ignore_unknown_columns => Off => Off
  • PHP Version:
PHP 5.6.19 (cli) (built: Apr 24 2016 12:31:51) 
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies
  • Operating System: Ubuntu 14.04
  • Installation type: zephir
  • Zephir version (if any): Version 0.9.4a-dev-121e9b4bf1
  • Server: Apache
@virgofx
Copy link
Contributor

virgofx commented Aug 20, 2016

Likely related to: #11819 -- Can we mark both of these as relevant for 3.0.2 milestone as this has been an issue for awhile. Sample reproducible code in #11819.

@Jurigag
Copy link
Contributor Author

Jurigag commented Aug 20, 2016

Yea but what is weird it works on php 7 though.

@sergeyklay sergeyklay added this to the 3.0.2 milestone Aug 20, 2016
@virgofx
Copy link
Contributor

virgofx commented Aug 26, 2016

Confirmed issue as well.

Backtrace

zend_std_object_get_class (object=0x7f13ae1cc918) at /usr/src/debug/php-5.6.25/Zend/zend_object_handlers.c:1528
1528            return zobj->ce;
(gdb) bt
#0  zend_std_object_get_class (object=0x7f13ae1cc918) at /usr/src/debug/php-5.6.25/Zend/zend_object_handlers.c:1528
#1  0x00007f13aef7836a in zephir_instance_of_ev () from /usr/lib64/php/modules/phalcon.so
#2  0x00007f13af1b84c5 in zim_Phalcon_Mvc_Application_handle () from /usr/lib64/php/modules/phalcon.so
#3  0x00007f13c119ebfb in dtrace_execute_internal (execute_data_ptr=<optimized out>, fci=<optimized out>, return_value_used=<optimized out>) at /usr/src/debug/php-5.6.25/Zend/zend_dtrace.c:97
#4  0x00007f13c12588a4 in zend_do_fcall_common_helper_SPEC (execute_data=<optimized out>) at /usr/src/debug/php-5.6.25/Zend/zend_vm_execute.h:560
#5  0x00007f13c11ecbe8 in execute_ex (execute_data=0x7f13c0ef1f20) at /usr/src/debug/php-5.6.25/Zend/zend_vm_execute.h:363
#6  0x00007f13c119ead9 in dtrace_execute_ex (execute_data=<optimized out>) at /usr/src/debug/php-5.6.25/Zend/zend_dtrace.c:73
#7  0x00007f13c1258d59 in zend_do_fcall_common_helper_SPEC (execute_data=<optimized out>) at /usr/src/debug/php-5.6.25/Zend/zend_vm_execute.h:592
#8  0x00007f13c11ecbe8 in execute_ex (execute_data=0x7f13c0ef0b50) at /usr/src/debug/php-5.6.25/Zend/zend_vm_execute.h:363
#9  0x00007f13c119ead9 in dtrace_execute_ex (execute_data=<optimized out>) at /usr/src/debug/php-5.6.25/Zend/zend_dtrace.c:73
#10 0x00007f13c11b187b in zend_execute_scripts (type=type@entry=8, retval=retval@entry=0x0, file_count=file_count@entry=3) at /usr/src/debug/php-5.6.25/Zend/zend.c:1341
#11 0x00007f13c114c7e2 in php_execute_script (primary_file=primary_file@entry=0x7ffcdbc8b910) at /usr/src/debug/php-5.6.25/main/main.c:2613
#12 0x00007f13c102c8bf in main (argc=<optimized out>, argv=<optimized out>) at /usr/src/debug/php-5.6.25/sapi/fpm/fpm/fpm_main.c:1989

Backtrace when built with zephir builddev

#0  0x00007f7b2bf9d5f7 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007f7b2bf9ece8 in __GI_abort () at abort.c:90
#2  0x00007f7b153b1e10 in zephir_do_memory_observe (var=0x7ffd80ba8c40, g=0x7f7b1d288a40 <phalcon_globals>) at /usr/share/cphalcon/ext/kernel/memory.c:549
#3  0x00007f7b153b1e7d in zephir_memory_observe (var=0x7ffd80ba8c40) at /usr/share/cphalcon/ext/kernel/memory.c:565
#4  0x00007f7b1545913b in zim_Phalcon_Dispatcher__dispatch (ht=0, return_value=0x7f7b0dcb10c8, return_value_ptr=0x7ffd80baa1a0, this_ptr=0x7f7b0dca3da0, return_value_used=1) at /usr/share/cphalcon/ext/phalcon/dispatcher.zep.c:898
#5  0x00007f7b2ee98bfb in dtrace_execute_internal (execute_data_ptr=<optimized out>, fci=<optimized out>, return_value_used=<optimized out>) at /usr/src/debug/php-5.6.25/Zend/zend_dtrace.c:97
#6  0x00007f7b153cb095 in zephir_call_function_opt (fci=0x7ffd80ba9f80, fci_cache=0x7ffd80ba9f50, info=0x7ffd80baa0c0) at /usr/share/cphalcon/ext/kernel/extended/fcall.c:1321
#7  0x00007f7b153c5077 in zephir_call_user_function (object_pp=0x7ffd80baa0a0, obj_ce=0x7f7b0dc5fe38, type=zephir_fcall_method, function_name=0x0, retval_ptr_ptr=0x7ffd80baa1a0, cache_entry=0x0, cache_slot=0, param_count=0, params=0x7ffd80baa190, 
    info=0x7ffd80baa0c0) at /usr/share/cphalcon/ext/kernel/fcall.c:570
#8  0x00007f7b153c56e4 in zephir_call_class_method_aparams (return_value_ptr=0x7ffd80baa1a0, ce=0x7f7b0dc5fe38, type=zephir_fcall_method, object=0x7f7b0dca3da0, method_name=0x7f7b159b6de5 "_dispatch", method_len=9, cache_entry=0x0, cache_slot=0, 
    param_count=0, params=0x7ffd80baa190) at /usr/share/cphalcon/ext/kernel/fcall.c:824
#9  0x00007f7b15452ce6 in zim_Phalcon_Dispatcher_dispatch (ht=0, return_value=0x7f7b0dcb0858, return_value_ptr=0x7ffd80baab90, this_ptr=0x7f7b0dca3da0, return_value_used=1) at /usr/share/cphalcon/ext/phalcon/dispatcher.zep.c:547
#10 0x00007f7b2ee98bfb in dtrace_execute_internal (execute_data_ptr=<optimized out>, fci=<optimized out>, return_value_used=<optimized out>) at /usr/src/debug/php-5.6.25/Zend/zend_dtrace.c:97
#11 0x00007f7b153cb095 in zephir_call_function_opt (fci=0x7ffd80baa5d0, fci_cache=0x7ffd80baa5a0, info=0x7ffd80baa710) at /usr/share/cphalcon/ext/kernel/extended/fcall.c:1321
#12 0x00007f7b153c5077 in zephir_call_user_function (object_pp=0x7ffd80baa6f0, obj_ce=0x7f7b0dc5fe38, type=zephir_fcall_method, function_name=0x0, retval_ptr_ptr=0x7ffd80baab90, cache_entry=0x0, cache_slot=0, param_count=0, params=0x7ffd80baa8a0, 
    info=0x7ffd80baa710) at /usr/share/cphalcon/ext/kernel/fcall.c:570
#13 0x00007f7b153c56e4 in zephir_call_class_method_aparams (return_value_ptr=0x7ffd80baab90, ce=0x7f7b0dc5fe38, type=zephir_fcall_method, object=0x7f7b0dca3da0, method_name=0x7f7b15e20dea "dispatch", method_len=8, cache_entry=0x0, cache_slot=0, 
    param_count=0, params=0x7ffd80baa8a0) at /usr/share/cphalcon/ext/kernel/fcall.c:824
#14 0x00007f7b15652c11 in zim_Phalcon_Mvc_Application_handle (ht=0, return_value=0x7f7b0dca3c80, return_value_ptr=0x7f7b2ebeb0a8, this_ptr=0x7f7b0dca39f8, return_value_used=1) at /usr/share/cphalcon/ext/phalcon/mvc/application.zep.c:323
#15 0x00007f7b2ee98bfb in dtrace_execute_internal (execute_data_ptr=<optimized out>, fci=<optimized out>, return_value_used=<optimized out>) at /usr/src/debug/php-5.6.25/Zend/zend_dtrace.c:97
#16 0x00007f7b2ef528a4 in zend_do_fcall_common_helper_SPEC (execute_data=<optimized out>) at /usr/src/debug/php-5.6.25/Zend/zend_vm_execute.h:560
#17 0x00007f7b2eee6be8 in execute_ex (execute_data=0x7f7b2ebebf20) at /usr/src/debug/php-5.6.25/Zend/zend_vm_execute.h:363
#18 0x00007f7b2ee98ad9 in dtrace_execute_ex (execute_data=<optimized out>) at /usr/src/debug/php-5.6.25/Zend/zend_dtrace.c:73
#19 0x00007f7b2ef52d59 in zend_do_fcall_common_helper_SPEC (execute_data=<optimized out>) at /usr/src/debug/php-5.6.25/Zend/zend_vm_execute.h:592
#20 0x00007f7b2eee6be8 in execute_ex (execute_data=0x7f7b2ebeab50) at /usr/src/debug/php-5.6.25/Zend/zend_vm_execute.h:363
#21 0x00007f7b2ee98ad9 in dtrace_execute_ex (execute_data=<optimized out>) at /usr/src/debug/php-5.6.25/Zend/zend_dtrace.c:73
#22 0x00007f7b2eeab87b in zend_execute_scripts (type=type@entry=8, retval=retval@entry=0x0, file_count=file_count@entry=3) at /usr/src/debug/php-5.6.25/Zend/zend.c:1341
#23 0x00007f7b2ee467e2 in php_execute_script (primary_file=primary_file@entry=0x7ffd80bad9c0) at /usr/src/debug/php-5.6.25/main/main.c:2613
#24 0x00007f7b2ed268bf in main (argc=<optimized out>, argv=<optimized out>) at /usr/src/debug/php-5.6.25/sapi/fpm/fpm/fpm_main.c:1989

@virgofx
Copy link
Contributor

virgofx commented Sep 1, 2016

There are actually 2 bugs.

  1. A return false when forwarding dispatcher in exception will cause segfault
  2. Exception handler is called twice when the dispatcher is not marked as finished

Here is the test script which outlines the 2 bugs. Adjust the commented sections in the 3 cases in the ExceptionHandler class outlined below.

index.php

<?php

/**
 * IndexController
 */
class IndexController extends \Phalcon\Mvc\Controller
{
    public function initialize()
    {
        $this->getDI()->getShared('view')->disable();
    }

    public function indexAction()
    {
        echo 'Index Action <br />';

        throw new Exception('Something happened');
    }

    public function errorAction()
    {
        echo 'Error Action <br />';
    }
}

/**
 * Dispatcher ExceptionHandler
 */
class ExceptionHandler extends \Phalcon\Mvc\User\Plugin
{
    public function beforeException(\Phalcon\Events\Event $event, \Phalcon\DispatcherInterface $dispatcher, \Exception $exception)
    {
        echo 'ExceptionHandler::beforeException() - ' . $exception->getMessage() . '<br />';


        ////////////////////////////////////////////////////////
        // Case 1:
        ////////////////////////////////////////////////////////

        // return false;

        // **Output** (OK)
        //      Index Action
        //      ExceptionHandler::beforeException() - Something happened


        ////////////////////////////////////////////////////////
        // Case 2 - Empty return or nothing at all
        ////////////////////////////////////////////////////////

        // return;

        // **Output** (Exception handler gets thrown twice)
        //      Index Action
        //      ExceptionHandler::beforeException() - Something happened
        //      ExceptionHandler::beforeException() - Something happened
        //      Fatal error: Uncaught exception 'Exception' with message 'Something happened' in /var/www/public/index.php:18 Stack trace: #0 [internal function]: IndexController->indexAction() #1 [internal function]: Phalcon\Dispatcher->callActionMethod(Object(IndexController), 'indexAction', Array) #2 [internal function]: Phalcon\Dispatcher->_dispatch() #3 [internal function]: Phalcon\Dispatcher->dispatch() #4 /var/www/public/index.php(87): Phalcon\Mvc\Application->handle() #5 {main} thrown in /var/www/public/index.php on line 18

        // The beforeException gets called again (resulting 2x) because we're not marked
        // as finished so the exception gets thrown up the stack
        // https://github.com/phalcon/cphalcon/blob/master/phalcon/dispatcher.zep#L595

        // **Expected Output**
        //      Index Action
        //      ExceptionHandler::beforeException() - Something happened
        //      Fatal error: Uncaught exception 'Exception' with message 'Something happened' in /var/www/public/index.php:18 Stack trace: #0 [internal function]: IndexController->indexAction() #1 [internal function]: Phalcon\Dispatcher->callActionMethod(Object(IndexController), 'indexAction', Array) #2 [internal function]: Phalcon\Dispatcher->_dispatch() #3 [internal function]: Phalcon\Dispatcher->dispatch() #4 /var/www/public/index.php(87): Phalcon\Mvc\Application->handle() #5 {main} thrown in /var/www/public/index.php on line 18

        ////////////////////////////////////////////////////////
        // Case 3:
        ////////////////////////////////////////////////////////

        // $dispatcher->forward(['action' => 'error']);
        // return false;

        // **Output** (SIGFAULT - Combination of forward + return false)

        // **Expected Output**
        //      Index Action
        //      ExceptionHandler::beforeException() - Something happened
        //      Error Action
    }
}


////////////////////////////////////////////////////////
// Bootstrap
////////////////////////////////////////////////////////

$di = new \Phalcon\Di\FactoryDefault();

$di->setShared('view', function() {
    return new \Phalcon\Mvc\View();
});

$di->setShared('dispatcher', function() {
    $eventsManager = new \Phalcon\Events\Manager();
    $eventsManager->attach('dispatch:beforeException', new ExceptionHandler());
    $dispatcher = new \Phalcon\Mvc\Dispatcher();
    $dispatcher->setEventsManager($eventsManager);
    return $dispatcher;
});

$application = new \Phalcon\Mvc\Application();
$application->setEventsManager(new \Phalcon\Events\Manager());
$application->setDI($di);

echo $application->handle()->getContent();

@virgofx
Copy link
Contributor

virgofx commented Sep 1, 2016

There's a 2 issues for why this isn't working. The primary issue is there exists a core Zephir bug with multiple try/catch blocks. The resulting Zephir code currently compiles bad c code for the JUMP frames as a result of:

https://github.com/phalcon/zephir/blob/master/Library/Call.php#L676

public function addCallStatusOrJump(CompilationContext $compilationContext)
{
  $compilationContext->headersManager->add('kernel/fcall');
  if (!$compilationContext->insideTryCatch) {
    $compilationContext->codePrinter->output('zephir_check_call_status();');
  } else {
    $compilationContext->codePrinter->output(
      'zephir_check_call_status_or_jump(try_end_' . $compilationContext->insideTryCatch . ');'
      //                                                               ^^currentTryCatch
    );
  } 
}

The outputting of the JUMP call always results in try_end_1 as the output is using the boolean flag opposed to the actual block which should be the currentTryCatch parameter.

@andresgutierrez or @sergeyklay - Can you guys update zephir with above fix^^

Once that's fixed in Zephir, the double dispatch error can be fixed by pulling out the commit that wraps the entire dispatch loop in a separate try/catch.

I'm working on a PR that will fix the double error handling while still ensuring proper bubbling of exceptions.

@sergeyklay
Copy link
Contributor

sergeyklay commented Sep 2, 2016

@virgofx

Could you please check 3.0.x branch?

git clone git@github.com:phalcon/cphalcon.git
cd cphalcon
git checkout 3.0.x

# Use latest Zephir here from master branch
zephir fullclean
zephir build

virgofx pushed a commit to virgofx/cphalcon that referenced this issue Sep 9, 2016
exceptions, and improved documentation/test-suite for dispatcher
components [phalcon#12154](phalcon#12154),
[phalcon#11819](phalcon#11819)
@sergeyklay sergeyklay modified the milestones: 3.0.2, 3.0.3 Nov 26, 2016
@sergeyklay sergeyklay modified the milestones: 3.0.3, 3.0.4 Dec 23, 2016
@sergeyklay sergeyklay modified the milestones: 3.0.4, 3.1.0, 3.1.x Feb 12, 2017
@sergeyklay sergeyklay removed this from the 3.1.0 milestone Feb 12, 2017
@sergeyklay sergeyklay modified the milestones: 3.1.x, 3.1.1 Mar 23, 2017
@sergeyklay sergeyklay modified the milestones: 3.1.1, 3.2.x, 3.2.0 Apr 5, 2017
@sergeyklay
Copy link
Contributor

Fixed in the 3.2.x branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A bug report status: medium Medium
Projects
None yet
Development

No branches or pull requests

5 participants