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

Closures do not report their class in stack traces #4560

Open
Ocramius opened this issue Jan 2, 2015 · 5 comments
Open

Closures do not report their class in stack traces #4560

Ocramius opened this issue Jan 2, 2015 · 5 comments

Comments

@Ocramius
Copy link
Contributor

Ocramius commented Jan 2, 2015

debug_backtrace() does not report the class that a particular Closure instance is bound to:

<?php

class Foo {
    public function bar() {
        $cb = function () {
            var_dump(debug_backtrace()[0]['class']);
        };

        $cb();
    }
}

(new Foo)->bar();

Example: http://3v4l.org/L1J8V (also verified on current master)

This makes it quite hard to emulate scope access limitations in userland.

@Ocramius
Copy link
Contributor Author

Ocramius commented Jan 3, 2015

After further inspection, I found the bits of code that require action, but I don't really know where to look to make all this happen:

  • if (ctx != nullptr && !fp->m_func->isClosureBody()) {
    - && !fp->m_func->isClosureBody() must be removed

  • Class* arGetContextClassImpl<false>(const ActRec* ar) {
    if (ar == nullptr) {
    return nullptr;
    }
    return ar->m_func->cls();
    }
    must be capable to extract closure bound class, something like following pseudo-code:

    template <>
    Class* arGetContextClassImpl<false>(const ActRec* ar) {
      if (ar == nullptr) {
        return nullptr;
      }
    
      if (ar->m_func->isClosureBody()) {
        // incomplete (probably wrong right now) - need to get a reference to the closure itself first
        return ActRec::decodeClass(ar->getThisOrClass());
      }
    
      return ar->m_func->cls();
    }

@paulbiss
Copy link
Contributor

paulbiss commented Jan 5, 2015

The ActRec may contain a this rather than a class so you'll need to check for that and extract the class from the ObjectData if it isn't a static closure, it may also contain neither. Also note that this will give you the bound class which may not even be related to the declaring class. It may also be different from the scope class. Lastly arGetContextClassImpl should probably return the scope class not the bound class, so you should make your changes in backtrace.cpp and leave that function alone.

@Ocramius
Copy link
Contributor Author

Ocramius commented Jan 5, 2015

and leave that function alone

Actually a good hint, as arGetContextClassImpl() is probably used in a lot of other contexts

@Ocramius
Copy link
Contributor Author

Another detail that slipped through is that also key 'object' is missing: http://3v4l.org/q0Cqj

@Ocramius
Copy link
Contributor Author

Ocramius commented Sep 1, 2015

Any news on this? Pretty much blocked by it for building Doctrine3 prototypes :-(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants